setTimeout 在 js 加載前的問題探究
阿新 • • 發佈:2019-01-15
fir 1.10 out 答案 ref article 而且 plugins html
先彈 1 時的代碼順序:
此時答案就比較明顯了:
先彈 2 是由於 js 加載阻斷了後面 alert 代碼的運行,
而使得主線程還未有代碼,因此 setTimeout 立馬循環到而先跑完了;
而先彈 1 則是 js 已被緩存,後續代碼立馬進入主線程,setTimeout 在事件循環中就靠後了。
雖然實操中不太可能會遇到這樣的使用場景,
但對瀏覽器的運行規則又有了一些別樣的眼光。
在試驗中,會更換多個瀏覽器查看,結果發現另一個有趣的現象: 各瀏覽器對事件循環的處理好像並不標準呢,而且 ajax 在 chrome 竟然也是和 Promise 一樣的微循環喲。
setTimeout 在 js 加載前的問題探究
思思放出一道題目,深究一下發覺很有意思<script>
setTimeout(() => {
alert(‘2‘);
}, 0)</script>
<script src="https://test.tms-uat.xuebangsoft.net/plugins/jquery-1.10.2.min.js"></script>
<script>
alert(‘1‘)
</script>
眾所周知, setTimeout 會進入事件循環,等待主線程空閑時才運行。
所以理論上來看,肯定都會先彈 1 再彈 2。
而當我 shift+F5 強刷時(或小概率),是先彈 2 的,後續直接 F5 還是先彈 1。
而如果將中間的 js 加載去掉,也不會先彈 2,
假如,setTimeout 前面也加上 js 加載,也不會先彈 2。
可見,此處好像 js 加載產生了一點微妙的化學反應。
後來通過 chrome 的 Performance 面板進行性能分析,
發現兩種情況下的代碼先後順序是不同的:
先彈 2 時的代碼順序:
在試驗中,會更換多個瀏覽器查看,結果發現另一個有趣的現象: 各瀏覽器對事件循環的處理好像並不標準呢,而且 ajax 在 chrome 竟然也是和 Promise 一樣的微循環喲。
setTimeout(function(){ alert(1) }, 0); for (var i=0; i<1e8; i++) {} new Promise((resolve) => { resolve(); }).then(function(){ alert(2); }); for (var i=0; i<1e8; i++) {} requestAnimationFrame(function(){ alert(3); }); for (var i=0; i<1e8; i++) {} $.get(‘./list.html‘, function(){ alert(4); }); for (var i=0; i<1e8; i++) {} alert(5); // chrome 結果 5 2 3 4 1 // firefox 結果 5 4 2 1 3
setTimeout 在 js 加載前的問題探究