8
  1. Coś wymaga zadania
  2. Coś innego wyciąga listę zadań z pamięci i sprawdza, czy są tam jakieś zadania.
  3. W przypadku zadań usuwa jedno, a mniejsza "lista zadań" zostaje ponownie zapisana.

między etapami 2 i 3 wejścia wyścig stan może wystąpić, jeśli występuje wiele żądań, a samo zadanie będzie służył dwukrotnie.Najlepszy sposób na zapobieganie wyścigowi w wielu wywołaniach API chrome.storage?

Czy prawidłową rozdzielczością jest "zablokowanie" "tabeli zadań", podczas gdy pojedyncze zadanie jest "wyrejestrowane", aby zapobiec innym żądaniom?

Co to jest rozwiązanie o najmniejszym wpływie na wydajność, takie jak opóźnienie wykonania, i jak powinno być ono zaimplementowane w javascript z interfejsem API chrome.storage?

Niektóre kod na przykład:

function decide_response () { 
    if(script.replay_type == "reissue") { 
      function next_task(tasks) { 
       var no_tasks = (tasks.length == 0); 
       if(no_tasks) { 
        target_complete_responses.close_requester(); 
       } 
       else { 
        var next_task = tasks.pop(); 
        function notify_execute() { 
         target_complete_responses.notify_requester_execute(next_task); 
        } 
        setTable("tasks", tasks, notify_execute); 
       } 
      } 
      getTable("tasks", next_tasks); 
    ... 
    } 
... 
} 
+0

Dobra edycja @ DJDavid98, dzięki. –

+0

Powinieneś spróbować użyć tego rodzaju wcięcia, aby kod był bardziej czytelny. Nawet jeśli nie jest to ostateczny wygląd kodu, nadal wygląda lepiej tutaj w Stack Overflow, a ludzie zwykle odpowiadają na pytania z większą motywacją, jeśli nie są brzydcy. – SeinopSys

+0

@ DJDavid98 Yers Jestem przekonany o tym, co mówisz. –

Odpowiedz

4

myślę, że można poradzić sobie bez zamka, korzystając z faktu, że JavaScript jest jednowątkowy w kontekście, nawet z asynchronicznym chrome.storage API. Tak długo, jak nie używasz chrome.storage.sync, to znaczy - jeśli są lub mogą nie być zmiany w chmurze, uważam, że wszystkie zakłady są wyłączone.

chciałbym zrobić coś takiego (napisany off mankietu, nie testowane, bez obsługi błędów):

var getTask = (function() { 
    // Private list of requests. 
    var callbackQueue = []; 

    // This function is called when chrome.storage.local.set() has 
    // completed storing the updated task list. 
    var tasksWritten = function(nComplete) { 
    // Remove completed requests from the queue. 
    callbackQueue = callbackQueue.slice(nComplete); 

    // Handle any newly arrived requests. 
    if (callbackQueue.length) 
     chrome.storage.local.get('tasks', distributeTasks); 
    }; 

    // This function is called via chrome.storage.local.get() with the 
    // task list. 
    var distributeTasks = function(items) { 
    // Invoke callbacks with tasks. 
    var tasks = items['tasks']; 
    for (var i = 0; i < callbackQueue.length; ++i) 
     callbackQueue[i](tasks[i] || null); 

    // Update and store the task list. Pass the number of requests 
    // handled as an argument to the set() handler because the queue 
    // length may change by the time the handler is invoked. 
    chrome.storage.local.set(
     { 'tasks': tasks.slice(callbackQueue.length) }, 
     function() { 
     tasksWritten(callbackQueue.length); 
     } 
    ); 
    }; 

    // This is the public function task consumers call to get a new 
    // task. The task is returned via the callback argument. 
    return function(callback) { 
    if (callbackQueue.push(callback) === 1) 
     chrome.storage.local.get('tasks', distributeTasks); 
    }; 
})(); 

Zadanie przechowuje żądania od konsumentów, jak wywołania zwrotne w kolejce w pamięci lokalnej. Gdy nadejdzie nowe żądanie, wywołanie zwrotne zostanie dodane do kolejki, a lista zadań zostanie pobrana iff jest to jedyne żądanie w kolejce. W przeciwnym razie możemy założyć, że kolejka jest już przetwarzana (jest to niejawna blokada, która umożliwia dostęp do listy zadań tylko jednemu wątkowi wykonania).

Po pobraniu listy zadań zadania są rozsyłane do żądań. Pamiętaj, że może wystąpić więcej niż jedno żądanie, jeśli pojawiło się więcej, zanim zakończy się pobieranie. Ten kod po prostu przekazuje wartość null do wywołania zwrotnego, jeśli jest więcej żądań niż zadań. Aby zamiast tego zablokować żądania, aż pojawi się więcej zadań, wstrzymaj nieużywane wywołania zwrotne i ponownie uruchom przetwarzanie żądań po dodaniu zadań. Jeśli zadania mogą być produkowane dynamicznie, a także zużyte, pamiętaj, że należy również zapobiegać tym warunkom wyścigu, ale nie jest to tutaj pokazane.

Ważne jest, aby uniemożliwić ponowne czytanie listy zadań, dopóki nie zostanie zapisana zaktualizowana lista zadań. Aby to osiągnąć, żądania nie są usuwane z kolejki, dopóki aktualizacja nie zostanie zakończona. Następnie musimy upewnić się, że przetwarzamy wszystkie żądania, które dotarły w międzyczasie (możliwe jest zwarcie wywołania do chrome.storage.local.get(), ale zrobiłem to w ten sposób dla uproszczenia).

Takie podejście powinno być dość wydajne w tym sensie, że powinno zminimalizować aktualizacje listy zadań, a jednocześnie reagować tak szybko, jak to możliwe. Nie ma wyraźnego blokowania ani czekania. Jeśli masz klientów zadań w innych kontekstach, skonfiguruj procedurę obsługi wiadomości chrome.extension, która wywołuje funkcję getTask().

Powiązane problemy