開發中常常使用setTimeout進行一些延遲操做。昨天忽然想了解下setTimeout的handler到底在隊列中的什麼位置特別好奇。今天特意來測試下。javascript
setTimeout() 方法用於在指定的毫秒數後調用函數或計算表達式。html
setTimeout(code,millisec)
參數 | 描述 |
---|---|
code | 必需。要調用的函數後要執行的 JavaScript 代碼串。 |
millisec | 必需。在執行代碼前需等待的毫秒數。 |
提示:setTimeout() 只執行 code 一次。若是要屢次調用,請使用 setInterval() 或者讓 code 自身再次調用 setTimeout()。java
以上定義來源於w3school.comajax
先了解下瀏覽器,瀏覽器是多線程的。瀏覽器
JS運行在瀏覽器中,是單線程的,每一個window一個JS引擎線程。既然是單線程的,的在某個特定的時刻只有特定代碼能被執夠行,並阻塞其它的代碼。(至於ajax的實現這裏就不說了。)多線程
來了解下setTimeout的簡單的原理:異步
setTimeout調用的時候,JavaScript引擎會啓動定時器timer,大約millisec(ms)之後執行code,當定時器時間到,就把該事件放到主事件隊列等待處理。函數
注意:學習
瀏覽器JavaScript線程空閒的時候纔會真正執行測試
爲何呢?由於當JavaScript線程的正在出來其餘JavaScript代碼時,其實以已經阻塞了其餘的代碼,其中包括的setTimeout的定時器部分的實現。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<script type="text/javascript">
function testHandler() { console.log("調用了setTimeout的函數"); } window.onload = function () { console.log("開始"); console.log("設置setTimeout 100ms"); setTimeout(testHandler,100); console.log("休眠1000ms"); sleep(1000); testNext(); console.log("結束"); } function testNext() { console.log("後續執行的函數"); } function sleep(number) { var now = new Date(); var exitTime = now.getTime() + number; while (true) { now = new Date(); if (now.getTime() > exitTime) return; } } </script>
</head>
<body>
</body>
</html>
最終瀏覽器輸出的結果:
此處setTimeout其實只延遲了100ms。而進setTimeout到結束中先模擬休眠了2000ms,而後再執行了testNext函數。可是從測試結果來看實際上testHandler倒是在整個隊列的最後。這就解釋了上訴中說的,setTimeout將code加入到隊列的操做必須是在線程空閒的時候纔會執行了。
上訴測試發現,實際應用中。setTimeout的millisec參數無論你設置多少,實際執行都是在線程的最後,由於在執行一個操做的時候,JavaScript確定是一直把代碼執行完後再走setTimeout綁定的code的。
那麼問題來了。setTimeout(handler,0)和setTimeout(handler,100)在單獨使用時,好像並無區別。(中間執行的代碼處理時間超過100ms時)
<script type="text/javascript">
function testHandler() { console.log("調用了setTimeout的函數"); } window.onload = function () { console.log("開始"); console.log("設置setTimeout 100ms"); setTimeout(testHandler,100); setTimeout(function () { console.log("調用了setTimeout的函數2"); }, 50); console.log("休眠1000ms"); sleep(1000); testNext(); console.log("結束"); } function testNext() { console.log("後續執行的函數"); } function sleep(number) { var now = new Date(); var exitTime = now.getTime() + number; while (true) { now = new Date(); if (now.getTime() > exitTime) return; } } </script>
輸出結果:
我的認爲millisec通常在多個setTimeout一塊兒使用的時,須要區分哪一個先加入到隊列的時候纔有用,不然均可以設置成setTimeout(handler,0)(異步操做不在討論範圍內)
以上哪有寫的不對的地方歡迎指正學習。^3^
歡迎轉載
轉載註明原創地址:http://www.cnblogs.com/Jersen/p/4887225.html