網(wǎng)站性能優(yōu)化(四)利用setTimeout延遲代碼執(zhí)行

眾所周知,JavaScript是單線程。當(dāng)JavaScript和用戶界面更新在同一個(gè)進(jìn)程中運(yùn)行团甲,JavaScript的執(zhí)行必然會(huì)阻止UI更新,反之亦然黍聂。

一般躺苦,可以通過(guò)控制JavaScript執(zhí)行時(shí)間(不超過(guò)100毫秒)來(lái)盡快更新UI,但是产还,總是有可能需要處理比較復(fù)雜的JavaScript程序匹厘,這時(shí),可以采用定時(shí)器安排代碼延遲執(zhí)行脐区,其能夠幫助你把長(zhǎng)時(shí)間運(yùn)行的腳步分解成一系列的小任務(wù)愈诚。

下面分兩個(gè)部分講解:

1. 事件輪詢(event loop)

關(guān)于事件輪詢的帖子很多(比如老阮的http://www.ruanyifeng.com/blog/2014/10/event-loop.html)。

參考下圖:


  1. 所有同步任務(wù)在主線程上執(zhí)行牛隅,形成執(zhí)行棧炕柔;
  2. 一旦觸發(fā)異步事件,比如媒佣,DOM event(點(diǎn)擊按鈕)匕累,ajax事件,定時(shí)器等等默伍,那么哩罪,該事件的處理結(jié)果(即callback事件)會(huì)放在另外一個(gè)隊(duì)列中-任務(wù)隊(duì)列授霸。
  3. 一旦執(zhí)行棧中同步任務(wù)執(zhí)行完畢,系統(tǒng)會(huì)讀取“任務(wù)隊(duì)列”际插,按照先入先出順序,依次執(zhí)行異步任務(wù)显设。

通過(guò)事件輪詢機(jī)制框弛,異步任務(wù)是不會(huì)阻塞界面更新,允許UI能夠盡快的響應(yīng)后續(xù)變化捕捂。
多個(gè)異步事件是無(wú)序執(zhí)行的的瑟枫,除了setTimeout/setInterval可以指定延遲時(shí)間,其他異步事件都無(wú)法確定何時(shí)被加入到“任務(wù)隊(duì)列”中指攒。

下面我們專門研究下setTimeout慷妙。

2. setTimeout

看一個(gè)簡(jiǎn)單的例子:

    var f1 = function(){
        console.log('this is setTimeout1!');
    };

    var f2 = function(){
        console.log('this is setTimeout2!');
    };

    var f3 = function(){
        console.log('this is setTimeout3!')
    };

    var f4 = function(){
        console.log('this is setTimeout4!')
    };

    function func1(){
        console.log('this is func1!');

        setTimeout(f1, 0);
        setTimeout(f2, 200);

        console.log('this is func1-end!');
        func2();

        function func2(){
            console.log('this is func2!');

            setTimeout(f3, 0);
            setTimeout(f4, 100);
            console.log('this is func2-end!');
        }
    }

    func1();

// 打印結(jié)果
this is func1!
this is func1-end!
this is func2!
this is func2-end!
this is setTimeout1!
this is setTimeout3!
this is setTimeout4!
this is setTimeout2!

利用Chrome developer timeline分析JavaScript執(zhí)行順序:

timeline1.png

可見,在UI繪制完畢之前允悦,會(huì)執(zhí)行func1函數(shù)中的console.log(XXX)膝擂,到了UI繪制完畢后,才開始執(zhí)行第一個(gè)setTimeout回調(diào)函數(shù)-f1隙弛。
根據(jù)延遲時(shí)間的不同架馋,以及執(zhí)行setTimeout的時(shí)間點(diǎn),會(huì)確定異步事件的“任務(wù)隊(duì)列”中的排隊(duì)順序全闷。

注意叉寂,setTimeout第二個(gè)參數(shù)表示任務(wù)何時(shí)被添加到“任務(wù)隊(duì)列”,而不是一定會(huì)在這段時(shí)間后執(zhí)行总珠。

timeline2.png

從上圖可見屏鳍,f1在第69.7ms時(shí)才被執(zhí)行,f1執(zhí)行完之后繼續(xù)執(zhí)行f3局服。

f4和f2的執(zhí)行時(shí)間如下圖:

timeline3.png
timeline4.png

3. 小結(jié)

根據(jù)event loop原理钓瞭,利用setTimeout可以延遲代碼執(zhí)行,并且不阻塞UI更新腌逢。

如果一個(gè)JavaScript執(zhí)行時(shí)間非常長(zhǎng)降淮,那么我們可以考慮用定時(shí)器分解任務(wù),不過(guò)搏讶,必須滿足下面兩個(gè)條件才適合用setTimeout:

  1. 處理過(guò)程不需要同步
  2. 數(shù)據(jù)不需要按順序處理

偽代碼如下:

function saveDocument(id) {
  var tasks = [openDocument, writeText, closeDocument, updateUI];
  setTimeout(function(){
    var task = tasks.shift();
    task(id);
    
    if (tasks.length > 0) {
      setTimeout(arguments.callee, 25);
    }
  }, 25);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末佳鳖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子媒惕,更是在濱河造成了極大的恐慌系吩,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妒蔚,死亡現(xiàn)場(chǎng)離奇詭異穿挨,居然都是意外死亡月弛,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門科盛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)帽衙,“玉大人,你說(shuō)我怎么就攤上這事贞绵±髀埽” “怎么了?”我有些...
    開封第一講書人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵榨崩,是天一觀的道長(zhǎng)谴垫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)母蛛,這世上最難降的妖魔是什么翩剪? 我笑而不...
    開封第一講書人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮彩郊,結(jié)果婚禮上前弯,老公的妹妹穿的比我還像新娘。我一直安慰自己焦辅,他們只是感情好博杖,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著筷登,像睡著了一般剃根。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上前方,一...
    開封第一講書人閱讀 52,807評(píng)論 1 314
  • 那天狈醉,我揣著相機(jī)與錄音,去河邊找鬼惠险。 笑死苗傅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的班巩。 我是一名探鬼主播渣慕,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼抱慌!你這毒婦竟也來(lái)了逊桦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤抑进,失蹤者是張志新(化名)和其女友劉穎强经,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寺渗,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匿情,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年兰迫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炬称。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡汁果,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玲躯,到底是詐尸還是另有隱情须鼎,我是刑警寧澤,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布府蔗,位于F島的核電站,受9級(jí)特大地震影響汞窗,放射性物質(zhì)發(fā)生泄漏姓赤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一仲吏、第九天 我趴在偏房一處隱蔽的房頂上張望不铆。 院中可真熱鬧,春花似錦裹唆、人聲如沸誓斥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)劳坑。三九已至,卻和暖如春成畦,著一層夾襖步出監(jiān)牢的瞬間距芬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工循帐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留框仔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓拄养,卻偏偏與公主長(zhǎng)得像离斩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瘪匿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容