1

Firefox의 크롬 부분 (즉, 콘텐츠가로드되기 전에)과 상호 작용하는 부트 스트랩 된 확장 프로그램이 있으며 확인을 위해 query an SQLite database이 필요합니다. 나는 동기 호출을 선호한다. 하지만 동기화 호출이 성능면에서 좋지 않아 UI 문제가 발생할 수 있으므로 비동기 DB 호출을해야합니다.Firefox Restartless Extension - while 회 돌이를 사용하여 좋은 대기 전략이 있습니까?

내 사용 사례는 다음과 같습니다

  • 가 완료되면 데이터베이스에

    • 만들기 aysnc 호출이 쉽게 '추가 처리'부분에 배치하여 처리 할 수 ​​있습니다, 지금은 추가 처리

    handleCompletion 부분의 executeAsync 기능.

    하지만이 구문이 실행되는 것과 관계없이 '추가 처리'가 필요합니다. 즉,이 DB 조회가 수행 될 수도 있고 실행되지 않을 수도 있습니다. 잘되지 않으면 잘 진행하십시오. 그럴 경우 기다려야합니다. 그래서 깃발 기반 전략을 사용하고 있습니다. 나는 깃발 handleCompletionCalledhandleError & handleCompletion 콜백 true에 설정했습니다. 추가적인 처리 부분에서

    , 나는 정말 많은이 있기 때문에 이에 대한 등 관찰자를 사용하지 않으려는 (내가

    while(handleCompletionCalled) { 
    // do nothing 
    } 
    
    //further processing 
    

    이 좋은 전략인가 할 또는 더 나은 뭔가를 할 수 내 전체 확장과 내 코드에서 그런 경우는 Observers로 채워질 것입니까?)

  • 답변

    2

    while 루프를 대기 상태로 사용하는 것은 심각한 아이디어입니다. 그렇게하면 UI를 정지하거나 루프를 통해 최대한 빨리 여러 번 빠르게 실행하여 지붕을 통해 CPU 사용량을 늘리는 결과가 발생합니다.

    비동기 프로그래밍에 대한 요점은 작업을 시작한 다음 다른 작업 인 콜백이 작업 완료 후 실행되거나 실패하는 것입니다. 이렇게하면 여러 작업을 시작하거나 처리를 전체 코드의 다른 부분으로 넘길 수 있습니다. 일반적으로이 콜백은 비동기 작업 완료에 따라 달라지는 모든 작업을 처리해야합니다. 콜백 함수 자체는 다른 처리를 수행하는 코드를 포함 할 필요가 없습니다. 완료된 비동기 작업에 대한 응답으로 일어날 필요가있는 작업을 완료 한 후에는 doOtherProcessing()과 같은 다른 함수를 호출 할 수 있습니다.

    여러 비동기를 실행하는 경우, 작업은 다음과 같은 모든 다른 콜백 함수의 끝에서 호출 될 때마다 작업과 하나의 함수에 대한 플래그함으로써 그들 모두의 완료를 기다릴 수

    function continueAfterAllDone(){ 
        if(task1Done && task2Done && task3Done && task4Done) { 
         //do more processing 
        }else{ 
         //Not done with everything, yet. 
         return; 
        } 
    } 
    

    이 작업은 배열 또는 작업 큐를 사용하여 임의의 수의 작업으로 확장 할 수 있습니다.이 대기열은 하드 코드 된 작업 집합이 아닌 모든 작업이 완료되었는지 확인합니다.

    대기 : 당신이 실행 다른 처리 경로를해야 할 것,하지만 비동기 동작 (들)의 완료를 기다려야하는 경우
    , 당신은 타이머를 설정하여 수행 된 대기를해야하거나 간격.계속 진행해야 할 조건이 발생했는지 다시 확인할 때까지 지정된 기간 동안 프로세서를 생산합니다.

    부트 스트랩 된 추가 기능에서 nsITimer 인터페이스를 사용하여 시간 초과 또는 간격 타이머를 구현해야 할 수 있습니다. 이는 초기화 코드를 실행할 때 <window>이 존재하지 않을 가능성이 있기 때문에 필요합니다 (즉, window.setTimeout()에 액세스 할 가능성이 없음).

    당신이 다른 작업에 대한 대기를 구현하기 위하여려고하는 경우에, 당신은 그것을 같이 할 수있다 :

    const Cc = Components.classes; 
    const Ci = Components.interfaces; 
    
    var asyncTaskIsDone = false; 
    var otherProcessingDone = false; 
    // Define the timer here in case we want to cancel it somewhere else. 
    var taskTimeoutTimer; 
    
    function doStuffSpecificToResultsOfAsyncAction(){ 
        //Do the other things specific to the Async action callback. 
        asyncTaskIsDone = true; 
        //Can either call doStuffAfterOtherTaskCompletesOrInterval() here, 
        // or wait for the timer to fire. 
        doStuffAfterBothAsyncAndOtherTaskCompletesOrInterval(); 
    } 
    
    function doStuffAfterBothAsyncAndOtherTaskCompletesOrInterval(){ 
        if(asyncTaskIsDone && otherProcessingDone){ 
         if(typeof taskTimeoutTimer.cancel === "function") { 
          taskTimeoutTimer.cancel(); 
         } 
         //The task is done 
        }else{ 
         //Tasks not done. 
         if(taskTimeoutTimer){ 
          //The timer expired. Choose to either continue without one of the tasks 
          // being done, or set the timer again. 
         } 
         //}else{ //Use else if you don't want to keep waiting. 
         taskTimeoutTimer = setTimer(doStuffAfterBothAsyncAndOtherTaskCompletesOrInterval 
                ,5000,false) 
         //} 
        } 
    } 
    
    function setTimer(callback,delay,isInterval){ 
        //Set up the timeout (.TYPE_ONE_SHOT) or interval (.TYPE_REPEATING_SLACK). 
        let type = Ci.nsITimer.TYPE_ONE_SHOT 
        if(isInterval){ 
         type = Ci.nsITimer.TYPE_REPEATING_SLACK 
        } 
        let timerCallback = { 
         notify: function notify() { 
          callback(); 
         } 
        } 
        var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); 
        timer.initWithCallback(timerCallback,delay,type); 
        return timer; 
    } 
    
    function main(){ 
        //Launch whatever the asynchronous action is that you are doing. 
        //The callback for that action is doStuffSpecificToResultsOfAsyncAction(). 
    
        //Do 'other processing' which can be done without results from async task here. 
    
        otherProcessingDone = true; 
        doStuffAfterBothAsyncAndOtherTaskCompletesOrInterval(); 
    } 
    

    파이어 폭스 시작시 초기화 코드 : 위의 코드는 내가 사용하는 것과 수정
    이없는 시작 작업을 지연 시키려면 Firefox UI가 표시되기 전에을 수행해야합니다.

    제 부가 기능 중 하나에서 수행해야 할 적절한 처리량이 있지만 사용자에게 Firefox UI가 표시 되려면 반드시이 필요합니다.이 경우는 이 절대적으로 필요하지 않습니다. [Performance best practices in extensions "을 참조하십시오.] 따라서 UI를 지연시키지 않기 위해 Firefox를 시작한 후 5 초 후에 실행되는 타이머와 콜백을 사용합니다. 이렇게하면 Firefox UI가 사용자에게보다 반응 할 수 있습니다. 그에 대한 코드는 다음과 같습니다 startupLater()에서 수행되는 것이 아닙니다, 반드시, 이전 광고에이 처음으로 사용자에 의해 활성화되는 데 필요한 모든 것을 포함하고 있습니까

    const Cc = Components.classes; 
    const Ci = Components.interfaces; 
    
    // Define the timer here in case we want to cancel it somewhere else. 
    var startupLaterTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); 
    
    function startupLater(){ 
        //Tasks that should be done at startup, but which do not _NEED_ to be 
        // done prior to the Firefox UI being shown to the user. 
    } 
    
    function mainStartup(){ 
        let timerCallback = { 
         notify: function notify() { 
          startupLater(); 
         } 
        } 
        startupLaterTimer = startupLaterTimer.initWithCallback(timerCallback,5000 
                      ,Ci.nsITimer.TYPE_ONE_SHOT); 
    } 
    

    하는 것으로. 내 경우에는 사용자가 추가 기능의 UI 버튼을 누르거나 컨텍스트 메뉴를 통해 호출하기 전에 수행해야하는 모든 작업이 필요합니다. 타임 아웃은 길어야 할 수 있지만 (예 : 10 초), 5 초이므로 개발 중에 테스트 할 때까지 오래 기다릴 필요가 없습니다. 사용자가 추가 기능의 UI 단추를 누른 후에 만 ​​수행 할 수있는 일회성/시작 작업도 있습니다.

    1. 일반적인 프로그래밍 문제 : 일부 프로그래밍 언어에서는 메인 코드에서 프로세서를 생산하지 않으면 콜백이 호출되지 않을 수 있습니다. 이 경우에는 while 루프에서 고정되어 종료되지 않습니다.