使用setimmediate實現可伸縮執行的腳本
看過我對JavaScript 性能優化相關的討論的同學們一定很了解我的一個癖好,就是將一大段的script分解成多個塊來執行。通過使用setTimeout(),你可以去改變特定代碼執行的時間,從而做到讓UI現場執行已經在隊列里的任務。比如,你可以通過這樣的方式把要執行的代碼在50ms后加到UI線程隊列里:
- setTimeout(function(){
- //do something
- }, 50)
那么,在50ms后,這個函數就會被添加到隊列里,并在輪到它的時候執行。調用setTimeout()方法可以允許當前的JavaScript任務完成從而下一個UI更新可以順利進行。
雖然我一直很支持使用setTimeout()來提高性能,但是還是存在幾個問題。***個并且是最重要的問題是不同的瀏覽器有著不一樣的時間精確度。IE8和更早的IE的時間精確度是15.6ms,而IE9,或者更新的瀏覽器,還有chrome的時間精確度已經到達4ms。所有的瀏覽器都強制給setTimeout設置了一個***延遲值,所以setTimeout(fn, 0)實際上在大于0ms的時間之后才會執行,具體取決于對應的時間精確度。
另一個是電源使用的問題。管理時間關系到筆記本或者手機的電池使用。Chrome曾經嘗試把時間精確度降低到1ms,結果發現會增加筆記本電池的損耗。***還是覺得把時間精確度設置回4ms。其他瀏覽器也做過類似的嘗試,不過許多油門計時器分辨率為1s。微軟發現時間精確度為1ms的時候,電池的使用時間會降低25%。實際上,IE9會判斷筆記本是否在使用電池的情況下運行,如果是電池,則時間精確度為15.6ms,如果是直接插的電源則時間精確度會降低到4ms。
來自W3C Web Performance Working Group的一個方案“ Efficient Script Yielding ”,定義了一個新的函數去實現腳本的分塊執行的setImmediate()方法。 這個方法接收一個函數作為參數,它可以讓這個函數在UI線程空閑的時候執行?;镜挠梅ǎ?/p>
- var id = setImmediate(function(){
- //do something
- });
setImmediate()函數會返回一個id,這個id可以通過clearImmediate()方法來取消這個過程。
我們也可以給它傳遞一些參數
- setImmediate(function(doc, win){
- //do something
- }, document, window);
用這個方式來傳遞可選的參數意味著你不需要總是使用一個閉包來讓函數包含一些有用的信息。
setImmediate()可以讓瀏覽器不需要去管理進程的定時器。不需要去等待更耗電的系統中斷,瀏覽器只需要等待UI隊列空閑,然后把新的JavaScript任務插入進去。Node.js的開發者會比較容易理解這個問題,因為process.nextTick()在自己的環境里做了相同的事情。
現在只有ie10支持這個方法,而且因為還沒有完全定下來,所以使用了msSetIntermediate()。IE10的Test Drive上也有一個setImmediate()的例子,展示了新方法帶來的性能提升。這個例子使用一個延遲來排列一些數據,排序之后的狀態會直接展示出來。
原文:http://w3ctech.com/b/archives/597
【編輯推薦】
- Google強推Dart語言替代JavaScript 意欲何為?
- 在.NET中使用Javascript作為腳本語言
- JavaScript設計模式深入分析
- JavaScript有關的10個秘密和怪癖
- 10個***Web移動開發JavaScript框架推薦