8
  1. 東西請求任務
  2. 其他東西將任務列表從存儲中取出,並檢查是否有任務存在。
  3. 如果有任務將其刪除,則將較小的「任務列表」存回存儲器。

步驟2和3之間的比賽中,如果多個請求發生,可能會發生狀況,同樣的任務將被送達兩次。防止在多個chrome.storage API調用中競爭條件的最佳方法?

正確的解決方案是「鎖定」「任務表」,而單個任務是「簽出」,以防止任何其他請求?

什麼是性能影響最小的解決方案,如延遲執行,以及如何在JavaScript中使用chrome.storage API實現?

例如有些代碼:

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

尼斯編輯@ DJDavid98,謝謝。 – 2013-02-24 11:48:50

+0

您應該嘗試使用這種縮進以使代碼更具可讀性。即使這不是最終代碼的外觀,它在Stack Overflow上看起來仍然更好,如果它們不難看,人們傾向於用更多的動機來回答問題。 – SeinopSys 2013-02-24 11:55:36

+0

@ DJDavid98 Yers我相信你說的話。 – 2013-02-24 14:36:11

回答

4

我想你可以通過一個事實,即JavaScript是單線程的上下文中,即使與異步chrome.storage API的優勢無鎖管理。只要你沒有使用chrome.storage.sync,那就是 - 如果有可能或者可能沒有來自雲的變化,我認爲所有的賭注都沒有。

我會做這樣的事情(書面即興,沒有測試,沒有錯誤處理):從消費者

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); 
    }; 
})(); 

這個商店的任務請求如在本地存儲隊列的回調。當新的請求到達時,回調被添加到隊列中,任務列表被提取iff這是隊列中唯一的請求。否則,我們可以假定隊列已經被處理(這是一個隱含的鎖,它只允許執行一行來訪問任務列表)。

當任務列表被提取時,任務被分配到請求。請注意,如果在獲取完成之前已經有更多人到達,則可能會有多個請求。如果有更多請求比任務更多,此代碼只會將null傳遞給回調函數。要在更多任務到達之前阻止請求,請保留未使用的回調,並在添加任務時重新啓動請求處理。如果任務可以動態生成以及消耗,請記住,需要阻止競爭條件,但此處不顯示。

重要的是要防止再次讀取任務列表,直到存儲更新的任務列表。要完成此操作,請求將不會從隊列中刪除,直到更新完成。然後,我們需要確保處理同時到達的任何請求(可以將對chrome.storage.local.get()的調用短路,但爲簡單起見,我是這樣做的)。

這種方法應該非常高效,因爲它應儘可能減少更新任務列表,同時儘可能快地響應。沒有明確的鎖定或等待。如果在其他上下文中有任務使用者,則設置調用getTask()函數的chrome.extension消息處理程序。