1、前言 html
因爲JavaScript程序爲單線程,所以在執行長時間的操做時(如循環和遞歸操做)到致使UI線程長期被阻塞,沒法響應用戶操做請求(如點擊按鈕等),讓用戶體驗大打折扣。因而想到將一個長時間操做切片成N個小操做並異步執行,例如jsDeferred中的 Deferred.repeat函數 就提供這樣的解決辦法,其實質就是經過 setTimeout事件 或 script元素 的 onerror/onload事件 來異步調用這些小操做,從而儘早釋放UI線程。git
從IE10開始引入了setImmediate接口來代替setTimeout來完成上述功能,下面將記錄該接口的資訊,因爲內容會涉及到event loop、調用棧等知識,而我對相關內容瞭解仍不全面,所以下面的內容如有紕漏請各位指正,謝謝!github
2、同步和異步調用 瀏覽器
因爲JavaScript是經過異步調用來儘早釋放UI線程,所以咱們先要了解同步和異步執行的具體含義:網絡
任務的執行實質上分爲兩步:①.執行,②.獲取執行結果。異步
同步執行:執行後等待直到獲取執行結果;函數
異步執行:執行後不等待,而是經過一系列手段(輪詢、事件監聽和event loop等)獲取執行結果,而在執行後和獲取結果前的那段時間能夠介入其餘任務操做。 oop
2、setTimeout(handler, 0)的問題 測試
因爲setTimeout存在時間精度,所以setTimeout(handler,0)中setTimeout事件插入事件隊列的延時一定大於0ms,而handler的執行延時則更大了。具體爲IE5~8和不插電源的IE9的時間精度爲15.6ms,插電源的IE9和其餘瀏覽器則爲4ms。spa
經微軟和Chrome團隊實驗所得下降時間精度將會大大縮短筆記本的續航時間,也是就說更耗電,所以即便瀏覽器廠商有能力縮短期精度,但基於多方面的考慮,依然保持上述的精度值。
3、setImmediate接口
對於經過異步執行的手段對任務切片,因爲UI線程獲得釋放從而提升用戶體驗,但相對於採用同步執行,總體的任務執行時間較被拉長,所以咱們但願切片的小操做越快執行越好。而setImmediate接口則是爲此而生的。
setImmediate(handler) 並不像 setTimeout(handler, 0) 由event loop檢測系統時間是否到點而後向事件隊列插入一個事件,而後調用事件的回調方法handler。而是監控UI線程的調用棧,一旦調用棧爲空則將handler壓棧。
理論上經過setImmediate執行異步調用的延時必定比經過setTimeout的短,但事實又是如何呢?
我在IE11上操做測試,setTimout的延時爲4ms左右,而setImmediate的延時爲2ms左右。
注意:
1. 經過setImmediate的異步調用的延時不是0ms哦!
2. 並且有時候setImmediate的延時比setTimeout的多1~2ms哦!
3. 並且setImmediate和setTimeout的延時均比img元素onerror事件的延時長哦!
推測:
1. 對於setImmediate的延時有時比setTimeout的要長,因爲setImmediate要先監控調用棧,若調用棧爲空才壓棧,那麼在壓棧以前event loop已經將setTimeout事件的回調函數壓棧了。
2. 對於二者均比img元素onerror事件的長,因爲設置img.src後立刻發起請求(不必定爲網絡IO)當加載失敗時onerror事件則會比setTimeout事件先加入事件隊列。
4、總結
本文內容紕漏之處請各位指正,謝謝!
尊重原創,轉載請註明來自:http://www.cnblogs.com/fsjohnhuang/p/4151595.html ^_^肥仔John
5、參考
http://developer.51cto.com/art/201109/292720.htm
http://msdn.microsoft.com/library/ie/hh920766.aspx
https://github.com/yuzujs/setimmediate
http://www.nczonline.net/blog/2011/09/19/script-yielding-with-setimmediate/