這個問題大概是這樣:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function postData() | |
{ | |
$.post('xxx.api', {}, function(data){ | |
// handle ajax event | |
}); | |
for (var i = 0; i < 100000; i++){ | |
// do some computation here ... | |
} | |
} | |
postData(); |
我想大概只有我才會傻傻的說要看 for loop 有多 heavy ... 我完全忘了考慮瀏覽器上的 JavaScript 環境都是 single thread,每一個 segment 都是一個 event request,而瀏覽器的 event queue 一次只有一個 event 能被處理。換句話說,當 postData 這個 function body segment 被執行的時候,是沒有任何人插的進去的。就算網路超快,Ajax request 立刻回來也沒機會立刻執行 onSuccess,一定要等到 postData segement 離開為止才有機會繼續處理 event queue 中的下一個 event!
我剎那間一驚,就是這個卡住我 UI 啊。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
for (var i = 0; i < 1000; i++) | |
{ | |
$(document.body).append($("<div class='entry'>Entry</div>")); | |
} |
最直覺得方式是這樣改:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
for (var i = 0; i < 1000; i++) | |
{ | |
function _(){ | |
$(document.body).append($("<div class='entry'>Entry</div>")); | |
}; | |
window.setTimeout(_, 0); | |
} |
但是這有個很嚴重的問題是如果 loop 裡有用到 i 的話會意想不到的 i 永遠都是 1000!
所以比較好的應該是:
setTimeout 是一個很好的 trick 來建立獨立的 event 丟到 event queue 裡面,而時間值給 0 代表的是儘快的執行。這樣一改寫之後 browser 就會有機會可以在中途處理 user input event 並且也能夠看起來即時地更新 UI。
所以比較好的應該是:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var i = 0; | |
function doAppend() | |
{ | |
if (i++ >= 1000){ | |
return; | |
} | |
$(document.body).append($("<div class='entry'>Entry</div>")); | |
setTimeout(doAppend, 0); | |
} | |
setTimeout(doAppend, 0); |
為什麼i 會停在 999?? 一時想不透耶
回覆刪除應該是 1000 啦 ... XDDD
刪除我了解了耶,謝謝Kenny 哥哥開拓我的視野
回覆刪除Hi KSWLee,
回覆刪除我沒辦法 reproduce 第二個 gist 的情況,
所以不太了解你說的
「for loop segment 整個是一個 event ,每個 append 的 function call 都被 append 到 event queue 後面」
這句話,
可以更詳細的解釋一下嗎?感謝!
附上 code : https://gist.github.com/3773721