setTimeout的異步

有時候,加載一些廣告的時候,我們用setTimeout實現異步,好讓廣告不會阻塞我們頁面的渲染。 

爲什麼setTimeout能夠實現異步呢?
 
看一段糟糕的代碼:
setTimeout(function() {
        while (true) {
        }
}, 100);
setTimeout(function() {
        alert('你好!');
}, 200);
 
setTimeout是異步,那麼,不管前面的代碼怎麼樣,他條件滿足了就會執行,但上面的代碼,由於任務隊列裏有一個死循環,而後面的彈出代碼在隊列的後面,循環不息,所以後面的永遠不會被執行到。
 
理解setTimeout,我個人認爲就是理解瀏覽器的執行模型。
 
瀏覽器是基於一個事件循環的模型,在這裏面,可以有多個任務隊列,比如render是一個隊列,響應用戶輸入是一個,script執行是一個。任務隊列裏放的是任務,同一個任務來源的任務肯定在同一個任務隊列裏。
任務有優先級,鼠標或鍵盤響應事件優先級高,大概是其他任務的3倍。
 
任務的執行過程中可能產生:
spin:不影響Event Loop並延後執行
pause:停止Event Loop並延後執行
 
spin,如setTimeout的異步方式,就是spin方式,當執行到setTimeout時,此任務先暫停並保存,繼續執行後續任務,當條件滿足時,再將setTimeout的執行任務放回任務隊列的後面,等待執行,假如前面有一個2s的任務,那原本是delay 1s的任務實際執行時會是在第3s的時候才執行。
 
pause,則是當在js中獲取元素的offsetWidth等需要更新dom操作的動作時發生的。當執行到此任務時,將停止事件循環的工作,也就是先停止js引擎解析執行,跳到渲染引擎更新用戶界面至當前狀態,這期間,不處理後續任務,當前執行的腳本暫停,界面保持響應,但無法處理輸入(事件循環停了),直到成功返回才繼續執行任務。
 
setTimeout的技巧使用:
 
1 <input type="text" value="a" name="input" onkeydown="alert(this.value)" />
2 <input type="text" value="a" name="input"
3 onkeydown="var me=this;setTimeout(function(){alert(me.value)},0)" />
 
第一個在keydown的時候,彈出來的是input裏原來的value,而第2個在keydown的時候,卻能彈出更新後的value,就是因爲setTimeout,雖然他的delay設置爲0,幾乎是即時觸發,但還是被添加到了執行隊列後面,但就是這個過程,渲染已經完成了,當他回調函數執行時,輸出來的已經是更新後的value了。
 
setTimeout知識點的面試題:
 
下面的代碼,多久之後會彈出'end'? 爲什麼?
 
複製代碼
1 var t = true;
2  
3 setTimeout(function(){ t = false; }, 1000);
4  
5 while(t){ }
6  
7 alert('end');
複製代碼
 
答案明顯,都在上面有解釋到了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章