亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript的計時器的工作原理

geekzhou / 1539人閱讀

摘要:創(chuàng)建了一個簡單的計時器,在經(jīng)過給定的時間后,回調(diào)函數(shù)將會被執(zhí)行。接受一個計時器由之前兩種計時器返回并且停止計時器回調(diào)函數(shù)的執(zhí)行。然而,我們可以注意到,當定時器再一次觸發(fā)在計時器回調(diào)函數(shù)正在執(zhí)行的時候,這一次定時器回調(diào)函數(shù)被丟棄了。

最近都在看一些JavaScript原理層面的文章,恰巧看到了jQuery的作者的一篇關(guān)于JavaScript計時器原理的解析,于是誠惶誠恐地決定把原文翻譯成中文,一來是為了和大家分享,二來是為了加深自己對于JavaScript的理解。原文鏈接:http://ejohn.org/blog/how-javascript-timers-work/

原文翻譯:

從基礎(chǔ)層面來講,理解JavaScript計時器的工作原理是很重要的。由于JavaScript是單線程的,所以很多時候計時器并不是表現(xiàn)得和我們的直觀想象一樣。讓我們從下面的三個函數(shù)開始,它們能夠讓我們有機會去構(gòu)造和操作計時器。

var id =setTimeout(fn, delay); 創(chuàng)建了一個簡單的計時器,在經(jīng)過給定的時間后,回調(diào)函數(shù)將會被執(zhí)行。這個函數(shù)會返回一個唯一的ID,便于在之后某個時間可以注銷這個計時器。

var id = setInterval(fn, delay); -和setTimeout類似,但是每經(jīng)過一段時間(給定的延時),所傳遞的函數(shù)就會被執(zhí)行一次,直到這個定時器被注銷。

clearInterval(id); clearTimeout(id); -接受一個計時器ID(由之前兩種計時器返回)并且停止計時器回調(diào)函數(shù)的執(zhí)行。

為了理解計時器的內(nèi)部工作原理,我們首先需要了解一個非常重要的概念:計時器設(shè)定的延時是沒有保證的。因為所有在瀏覽器中執(zhí)行的JavaScript單線程異步事件(比如鼠標點擊事件和計時器)都只有在它有空的時候才執(zhí)行。這最好通過圖片來說明,就如下面這張圖所示:

這一張圖片里面有很多信息需要慢慢消化,但是徹底地理解這張圖片將會讓你對JavaScript異步執(zhí)行是如何工作的有一個更好的認識。這張圖片是從一維的角度來闡述的:在垂直方向是以毫秒計的時間,藍色的塊代表了

當前正在執(zhí)行的JavaScript代碼段。比如第一段JavaScript執(zhí)行了大概18毫秒,鼠標點擊事件大概執(zhí)行了11毫秒。

由于JavaScript每次只能執(zhí)行一段代碼(基于它單線程的特性),所以所有這些代碼段都阻塞了其他異步事件的執(zhí)行。這就意味著,當一件異步事件(比如鼠標點擊,計時器觸發(fā)和一個XMLHttpRequest 請求完成)觸發(fā)的時候,這些事件的回調(diào)函數(shù)將排在執(zhí)行隊列的最后去等待執(zhí)行(排隊的方式因瀏覽器不同而不同,這里只是一個簡化)。

一開始,在第一段代碼段內(nèi),兩個計時器被初始化:一個10ms的setTimeout 和一個10ms的setInterval。由于計時器在哪兒初始化就在那兒開始計時,所以實際上計時器在第一段代碼執(zhí)行完成之前就觸發(fā)了。然而,計時器的回調(diào)函數(shù)并不是立即執(zhí)行了(單線程限制了不能這樣做),相反的是,回調(diào)函數(shù)排在了執(zhí)行隊列的最后,等到下一個有空的時間去執(zhí)行。

此外,在第一個代碼塊內(nèi)我們看到了一個鼠標點擊事件發(fā)生了。與之相關(guān)的javascript異步事件(我們不可能預測用戶會在什么時候去采取這樣的動作,因此這個事件被視為異步的)并不會立即執(zhí)行。和計時器一樣的是,它被放到了隊列的最后去等待執(zhí)行。

在第一個代碼快執(zhí)行完成的時候,瀏覽器會立即發(fā)出這樣的詢問:誰正在等待執(zhí)行?這個時候,鼠標點擊處理程序和計時器回調(diào)函數(shù)都在等待執(zhí)行。瀏覽器選擇了其中一個(鼠標點擊回調(diào)函數(shù))并且立即執(zhí)行它。為了執(zhí)行,計時器會等到下一個可能執(zhí)行的時間。

我們注意到,當鼠標點擊事件對應的處理程序正在執(zhí)行的時候,第一個定時回調(diào)函數(shù)也要執(zhí)行了。同定時計時器一樣,它也在隊列的后面等待執(zhí)行。然而,我們可以注意到,當定時器再一次觸發(fā)(在計時器回調(diào)函數(shù)正在執(zhí)行的時候),這一次定時器回調(diào)函數(shù)被丟棄了。如果在執(zhí)行一大塊代碼塊的時候,你把所有的定時回調(diào)函數(shù)都放在隊列的最后,結(jié)果就是一大串定時回調(diào)函數(shù)將會沒有間隔的一起執(zhí)行,直到完成。相反,在把更多定時回調(diào)函數(shù)放到隊列之前,瀏覽器會靜靜的等待,知道隊列中的所有定時回調(diào)函數(shù)都執(zhí)行完成。

事實上,我們可以看到,當interval回調(diào)函數(shù)正在執(zhí)行的時候,interval第三次被觸發(fā)。這給我們一個很重要的信息:interval并不關(guān)心當前誰在執(zhí)行,它的回調(diào)函數(shù)會不加區(qū)分地進入隊列,即使存在這個回調(diào)函數(shù)會被丟棄的可能。

最后,當?shù)诙€定時回調(diào)函數(shù)完成執(zhí)行的時候,我們可以看到j(luò)avascript引擎已經(jīng)沒有什么需要執(zhí)行了。這意味著,瀏覽器現(xiàn)在正在等待一個新的異步事件的發(fā)生。我們可以看到在50ms的時候,定時回調(diào)函數(shù)再一次被觸發(fā)。然而,這一次,沒有其他代碼阻塞他的執(zhí)行了,所以他立即執(zhí)行了定時回調(diào)函數(shù)。

讓我們看一個例子來更好地闡述setTimeout 和setInterval的區(qū)別。

1 setTimeout(function(){
2     /* Some long block of code... */
3     setTimeout(arguments.callee, 10);
4 }, 10);
5  
6 setInterval(function(){
7     /* Some long block of code... */
8 }, 10);

第一眼看上去這兩段代碼在功能上是等價的,但事實上卻不是。值得注意的是,setTimeout 這段代碼會在每次回調(diào)函數(shù)執(zhí)行之后至少需要延時10ms再去執(zhí)行一次(可能是更多,但是不會少)。但是setInterval會每隔10ms就去嘗試執(zhí)行一次回調(diào)函數(shù),不管上一個回調(diào)函數(shù)是不是還在執(zhí)行。

從這里我們能夠?qū)W到很多,讓我們來概括一下:

javascript引擎只有一個線程,迫使異步事件只能加入隊列去等待執(zhí)行。

在執(zhí)行異步代碼的時候,setTimeout 和setInterval 是有著本質(zhì)區(qū)別的。

如果計時器被正在執(zhí)行的代碼阻塞了,它將會進入隊列的尾部去等待執(zhí)行直到下一次可能執(zhí)行的時間出現(xiàn)(可能超過設(shè)定的延時時間)。

如果interval回調(diào)函數(shù)執(zhí)行需要花很長時間的話(比指定的延時長),interval有可能沒有延遲背靠背地執(zhí)行。

上述這一切對于理解js引擎是如果工作的無疑是很重要的知識,尤其是大量的典型的異步事件發(fā)生時,對于構(gòu)建一個高效的應用代碼片段來說是一個非常有利的基礎(chǔ)。

個人見解:

翻譯完成之后,感覺對于javascript異步有了新的認識,但是可能初學者看不太懂這篇文章,于是寫了一個demo,運行在nodejs環(huán)境下(瀏覽器不容易模擬)

 1 var startTime = new Date();
 2 
 3 //初始化計時器
 4 var start = setTimeout(function() {
 5     var end = new Date();
 6     console.log("10ms的計時器執(zhí)行完成,距離程序開始" + (end - start) + "ms");
 7 }, 10);
 8 
 9 //模擬鼠標點擊事件
10 function asyncReal(data, callback) {
11     process.nextTick(function() {
12         callback();      
13      });
14 }
15 var asyncStart = new Date();
16 asyncReal("yuanzm", function() {
17     var asyncEnd = new Date();
18     console.log("模擬鼠標執(zhí)行事件完成,花費時間" + (asyncEnd - asyncStart) + "ms");
19 })
20 
21 //設(shè)定定時器
22 count = 1;
23 var interval = setInterval(function() {
24     ++count;
25     if(count === 5) {
26         clearInterval(interval);
27     }
28     console.log("定時器事件");
29 },10);
30 
31 //模擬第一階段代碼執(zhí)行
32 var first = [];
33 var start = new Date();
34 for(var i = 0;i < 10000000;i++){
35     first.push(i);
36 }
37 var end = new Date();
38 console.log("第一階段代碼執(zhí)行完成,用時" + (end - start) + "ms");

運行結(jié)果如下:

我們按照文中的原理來解釋一下:

一開始設(shè)定的計時器并不是在10ms后立即執(zhí)行,而是被添加到了隊列后面,等到第一階段代碼執(zhí)行完成才執(zhí)行,距離開始的時間也不是設(shè)定的10ms

鼠標點擊事件同樣因為是異步事件,添加到了隊列后面,等到第一階段代碼執(zhí)行完成的時候才執(zhí)行。

鼠標點擊事件先于計時器事件添加到隊列后面

最后定時器才能執(zhí)行

  

鄭重聲明
本文章屬于個人原創(chuàng),如需轉(zhuǎn)載,請加上原文鏈接:
http://segmentfault.com/a/1190000002633108
另外同樣可以在博客園上面查看本文章:http://www.cnblogs.com/yuanzm/p/4126762.html
也歡迎Follow我的Github:https://github.com/yuanzm

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/85584.html

相關(guān)文章

  • javascript時器工作原理

    摘要:說到中的定時器,我們肯定會想到和這兩個函數(shù)。第一個回調(diào)一執(zhí)行,又開啟了第二個,這個定時器也是期望延時之后能夠執(zhí)行它的回調(diào)函數(shù)。可以用下面的圖來概括總結(jié)上面對定時器執(zhí)行原理進行了簡要的分析,希望能夠幫助我們更深入的理解。 說到 javascript 中的定時器,我們肯定會想到 setTimeout() 和 setInterval() 這兩個函數(shù)。本文將從 事件循環(huán)(Event Loop)...

    godlong_X 評論0 收藏0
  • Javascript時器那些事兒

    摘要:一什么是定時器提供了一些原生方法來實現(xiàn)延時去執(zhí)行某一段代碼,下面來簡單介紹一下設(shè)置一個定時器,在定時器到期后執(zhí)行一次函數(shù)或代碼段定時器延遲后執(zhí)行的函數(shù)延遲后執(zhí)行的代碼字符串,不推薦使用原理類似延遲的時間單位毫秒,默認值為向延遲函數(shù)傳遞而外的 一、什么是定時器 JS提供了一些原生方法來實現(xiàn)延時去執(zhí)行某一段代碼,下面來簡單介紹一下 setTimeout: 設(shè)置一個定時器,在定時器到期后執(zhí)行...

    Riddler 評論0 收藏0
  • 談談我對js中定時器一點理解

    摘要:這兩個函數(shù)接受定時器的例如我們上面提到的兩個函數(shù)產(chǎn)生的定時器,并停止對定時器中指定函數(shù)的調(diào)用。注意,定時器雖然觸發(fā)了,但是并不會立即執(zhí)行,它只是把需要延遲執(zhí)行的函數(shù)加入了執(zhí)行隊列,在線程的某一個可用的時間點,這個函數(shù)就能夠得到執(zhí)行。 擼了今年阿里、頭條和美團的面試,我有一個重要發(fā)現(xiàn)....... javascript定時器工作原理是一個重要的基礎(chǔ)知識點。因為定時器在單線程中工作,它們表...

    frontoldman 評論0 收藏0
  • 【翻譯】javascript 動畫原理淺析

    摘要:動畫原文通常,框架會為你處理動畫。整個的動畫過程被分成了很小的步驟,每一個步驟被定時器調(diào)用。因為定時器的周期非常短,所以動畫看起來是連續(xù)的。已經(jīng)過去的動畫時間作為分子,計算每一幀通過公式。線性的使動畫以固定的速度進行。 動畫 原文:http://javascript.info/tutori... 通常,框架會為你處理動畫。但是,你可能想知道僅僅用javascript怎么來實現(xiàn)動畫,和可...

    Worktile 評論0 收藏0
  • 瀏覽器工作原理整理

    摘要:渲染引擎渲染引擎也稱為瀏覽器內(nèi)核,主要時在瀏覽器窗口中顯示所請求的內(nèi)容,這是每個瀏覽器的核心部分。 瀏覽器的結(jié)構(gòu) 瀏覽器的主要組件包括: 用戶界面——包括地址欄、前進/后退按鈕、書簽菜單等。除了瀏覽器主窗口顯示用戶請求的頁面外,其他顯示的各個部分都屬于用戶界面。 用戶界面后端——用于繪制基本的窗口小部件,比如組合框和窗口。其公開了與web應用無關(guān)的通用接口,而在底層使用操作系統(tǒng)的用戶...

    jzman 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<