2009-09-20 42 views
6

我正在寫一個無處不在的插件長時間的函數回調爲ajax查詢阻止了GUI線程導致Firefox鎖定。有沒有一種正確的方式來在JavaScript的協作線程意義上「屈服」?

顯而易見的解決方案似乎是使用某種延遲執行(即我們要定期添加執行此查詢函數到事件隊列的末尾,然後允許執行其他命令。

我能想到這樣做的唯一方法是使用的setTimeout爲零的超時...這是保證工作,或者是有這樣做的更好的方法。

+0

你是怎麼做AJAX的?如果您正在加載腳本標記,則可能會阻止(瀏覽器阻止,直到腳本返回)。 – 2009-09-21 04:16:06

+0

我正在使用jQuery.get – user47741 2009-09-21 13:46:16

回答

7

使用setTimeout與一個非常小的超時(0或幾乎爲零,如果你覺得偏執)是在瀏覽器上下文中執行此操作的唯一方法。工作得很好,非常可靠,但一定要足夠頻繁,但不要太經常 ,因爲它需要一段時間才能回到你身邊(當然,在計算機意義上的「一段時間」它幾乎是瞬時的[用人的話來說,你可能正在做其他事情])。

+2

所有現代瀏覽器實現都將setTimeout限制在〜10ms(基本上在所有非Windows系統上爲10ms,其中定時器分辨率要求<16ms定時器對功耗有顯着影響)。所以你並不需要擔心縮短超時時間。 – olliej 2009-09-20 23:32:34

+1

@olliej:那是過時的信息(如果它在'09中是正確的,但是那也不是我的經驗)。瀏覽器的處理比這更復雜,這取決於'setTimeout'調用的起源。這是[幾年前在HTML5規範中編纂](http://www.w3.org/TR/html5/webappapis.html#timer-initialization-steps),但正如我所說,供應商已經在玩(不同)之前的遊戲。短版本:如果你的代碼沒有被定時器調用,你可以使用0,而現代瀏覽器會得到**非常**。 – 2015-10-21 11:57:21

3

請確保您使用異步請求作爲同步請求阻止瀏覽器(這將解釋GUI鎖定)。

如果這不是你的問題,我想你想要這樣的任務隊列。

var queue = []; 

queue.push(someTaskFunction); 
queue.push(anotherTaskFunction); 
// ... 

var runQueue = (function() { 
    var len = queue.length, task = 0; 
    for (; task < len; task++) { 
     yield queue[task](); 
    } 
}()); 

呼叫runQueue.next()執行下一個任務。用try..catch語句包裝它:

try { 
    runQueue.next(); 
} catch (e if (e instanceof StopIteration)) {} 
+0

該調用是異步的 – user47741 2009-09-20 22:14:41

+0

酷 - 我不知道發電機已被添加到JavaScript。我理解其他任務可以在函數返回時進行控制嗎? – user47741 2009-09-20 22:18:04

+0

請注意,生成器對於JavaScript來說比較新,不一定得到廣泛支持。 – 2009-09-20 22:25:34

相關問題