成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

談?wù)勎覍s中定時器的一點理解

frontoldman / 1740人閱讀

摘要:這兩個函數(shù)接受定時器的例如我們上面提到的兩個函數(shù)產(chǎn)生的定時器,并停止對定時器中指定函數(shù)的調(diào)用。注意,定時器雖然觸發(fā)了,但是并不會立即執(zhí)行,它只是把需要延遲執(zhí)行的函數(shù)加入了執(zhí)行隊列,在線程的某一個可用的時間點,這個函數(shù)就能夠得到執(zhí)行。

擼了今年阿里、頭條和美團的面試,我有一個重要發(fā)現(xiàn).......

javascript定時器工作原理是一個重要的基礎(chǔ)知識點。因為定時器在單線程中工作,它們表現(xiàn)出的行為很直觀。我們該如何創(chuàng)建和維護定時器呢?要從如下三個函數(shù)(都是定義在全局作用域,在瀏覽器中就是window的方法)說起:

var id=setTimeout(fn,delay);
-初始化一個只執(zhí)行一次的定時器,這個定時器會在指定的時間延遲delay之后調(diào)用函數(shù)fn,該setTimeout函數(shù)返回定時器的唯一id,我們可以通過這個id來取消定時器的執(zhí)行。

var id=setInvertal(fn,delay);
-與setTimeout類似,只是它會以delay為周期,反復(fù)調(diào)用函數(shù)fn,直到我們通過id取消該定時器。

clearInterval(id);clearTimeout(id);

-這兩個函數(shù)接受定時器的id(例如我們上面提到的兩個函數(shù)產(chǎn)生的定時器id),并停止對定時器中指定函數(shù)的調(diào)用。

要深入理解定時器工作原理,我們需要探索一個重要的概念:定時器指定的延遲時間并不能得到保證。在瀏覽器中,因為所有的javascript代碼都運行在單一線程之中,異步事件(如鼠標(biāo)點擊,定時器)只有在他們被觸發(fā)的時候他們的回調(diào)才有機會得以執(zhí)行。我們可以用下圖說明:

圖中包含大量的信息,吸收并理解這些信息,能幫助我們領(lǐng)悟“異步的javascript代碼是如何工作的”。這個圖是一維的,垂直方向是時間,以毫秒為單位。藍色的盒子代表正在執(zhí)行的javascript代碼所占時間片段。例如 第一個javascript塊執(zhí)行時間約18ms,第二個鼠標(biāo)點擊塊執(zhí)行了約11ms,其他塊類似。

因為單線程的緣故,在同一時間只能執(zhí)行一條javascript代碼,每一個代碼塊(藍色盒子)都會阻塞其他異步事件的執(zhí)行。這就意味著,當(dāng)一個異步事件發(fā)生的時候(例如鼠標(biāo)點擊,定時器觸發(fā),一個XMLHttpRequest 請求完成),它進入了代碼的執(zhí)行隊列,執(zhí)行線程空閑時會依照該執(zhí)行隊列中順序依次執(zhí)行代碼。(如何將異步事件加入隊列,不同瀏覽器,他們的實現(xiàn)可能有所差異,所以這里我們將其簡單化)。

開始的時候,在Javascript代碼塊(第一個盒子),初始化了兩個定時器,一個10ms延遲的setTimeout 和10ms的setInterval。這些定時器可能會在我們第一個代碼塊執(zhí)行結(jié)束之前就觸發(fā),這取決于定時器在第一個代碼塊中啟動的位置和時間。注意,定時器雖然觸發(fā)了,但是并不會立即執(zhí)行,它只是把需要延遲執(zhí)行的函數(shù)加入了執(zhí)行隊列,在線程的某一個可用的時間點,這個函數(shù)就能夠得到執(zhí)行。

當(dāng)?shù)谝粋€Javascript代碼初始化塊執(zhí)行結(jié)束,瀏覽器立即提出一個問題:誰在等待著被執(zhí)行? 在這個案例中鼠標(biāo)點擊時間的處理程序和一個定時器(setTimeout)都在等待。瀏覽器選擇一個并執(zhí)行(這里是鼠標(biāo)點擊事件的處理程序)。定時器就需要等待下一個可用時間來執(zhí)行。

需要注意的是當(dāng)鼠標(biāo)點擊事件處理程序執(zhí)行的時候,第一個interval定時器觸發(fā)了。和timeout定時器一樣,他的回調(diào)函數(shù)被加入了執(zhí)行隊列,等待執(zhí)行。然而,還需要注意到當(dāng)interval定時器再次觸發(fā),這個時候timeout定時器的回調(diào)函數(shù)正在執(zhí)行,此時這個interval的觸發(fā)被放棄了。假想(瀏覽器不這樣做),在一個占用時間很多的初始化定時器的代碼塊中,所有的interval觸發(fā)都把回調(diào)加入執(zhí)行隊列,當(dāng)初始化代碼塊結(jié)束后,執(zhí)行隊列中已經(jīng)累加了大量的定時器回調(diào)函數(shù),結(jié)果就會出現(xiàn)大量的interval回調(diào)函數(shù)無間隔的執(zhí)行,直到該執(zhí)行隊列清空。所以瀏覽器在講一個interval回調(diào)加入執(zhí)行隊列前,會檢查執(zhí)行隊列,如果其中存在尚未執(zhí)行的interval回調(diào)那么就等待,直到當(dāng)前執(zhí)行隊列中沒有相應(yīng)interval的回調(diào)以后才會繼續(xù)入隊interval回調(diào)。

事實上,如圖,我們看見在第一個Interval的回調(diào)執(zhí)行的時候(之前進入執(zhí)行隊列),第三個interval觸發(fā)了,這想我們展示一個重要的現(xiàn)象:Interval不關(guān)心當(dāng)前正在執(zhí)行的代碼,他們會不加選擇的添加回調(diào)到執(zhí)行隊列,盡管這意味著兩個interval回調(diào)函數(shù)執(zhí)行的時間間隔被犧牲。這里第一個interval回調(diào)執(zhí)行結(jié)束后,緊跟著第三個interval的回調(diào)馬上得到執(zhí)行,中間沒有印象中應(yīng)該有的10ms間隔。

最終,在第三個interval的回調(diào)執(zhí)行結(jié)束后,我們看見執(zhí)行隊列中沒有等待javascript引擎執(zhí)行的代碼,這就意味著,瀏覽器現(xiàn)在等待新的異步事件的發(fā)生,在50ms的刻度處interval再次觸發(fā),此時沒有什么會阻塞javascript引擎,這個interval回調(diào)會立即執(zhí)行。

讓我們看一個例子來闡明,setInterval和setTimeout的不同,

setTimeout(function(){
    /* Some long block of code... */
    setTimeout(arguments.callee, 10);
  }, 10);
 
  setInterval(function(){
    /* Some long block of code... */
  }, 10);

看第一眼,會覺得這兩段代碼功能相同,實際上,他們是不同的。

   需要注意到,setTimeout的回調(diào)函數(shù)的執(zhí)行總是保證了至少10ms的間隔(與上一個回調(diào)的執(zhí)行相比,實際執(zhí)行時,這個間隔可能變長,但是不可能更少),但是setInterval會嘗試每隔10ms執(zhí)行一次回調(diào),不管上一個回調(diào)函數(shù)時候已經(jīng)執(zhí)行完畢。(很多類庫的動畫都是使用的setTimeout實現(xiàn))

這里我們學(xué)到很多,總結(jié)一下:

javascript引擎是單線程的,會迫使異步事件進入執(zhí)行隊列,等待執(zhí)行。

setTimeout和setInterval在執(zhí)行異步代碼時從根本上是有所不同的。

如果一個定時器事件被阻塞,使得它不能立即執(zhí)行,那么它會被延遲,直到下一個可能的時間點,才被執(zhí)行(這可能比你指定的delay時間要長)

Interval的回調(diào)有可能‘背靠背’無間隔的執(zhí)行,這種情況是說interval的回調(diào)函數(shù)的執(zhí)行時間比你指定的delay時間還要長

  這些都是構(gòu)建javascript應(yīng)用程序非常重要的知識。了解javascript Engine是如何工作的,特別存在大量的異步事件發(fā)生,為構(gòu)建高級應(yīng)用程序代碼打下基礎(chǔ)。

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

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

相關(guān)文章

  • 10分鐘理解JS引擎的執(zhí)行機制

    摘要:深入理解引擎的執(zhí)行機制靈魂三問為什么是單線程的為什么需要異步單線程又是如何實現(xiàn)異步的呢中的中的說說首先請牢記點是單線程語言的是的執(zhí)行機制。 深入理解JS引擎的執(zhí)行機制 1.靈魂三問 : JS為什么是單線程的? 為什么需要異步? 單線程又是如何實現(xiàn)異步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.說說setTimeout 首先,請牢記2...

    zzbo 評論0 收藏0
  • 談?wù)?/em>我對面向?qū)ο笠约邦惻c對象的理解

    showImg(https://segmentfault.com/img/remote/1460000007103938?w=391&h=247); 文章最初發(fā)表于我的個人博客非典型性程序猿 對于剛接觸JAVA或者其他面向?qū)ο缶幊陶Z言的朋友們來說,可能一開始都很難理解面向?qū)ο蟮母拍钜约邦惡蛯ο蟮年P(guān)系。筆者曾經(jīng)帶過一個短期培訓(xùn)班教授java入門基礎(chǔ),在最后結(jié)束課程的時候,還有很多同學(xué)不太理解面向?qū)ο?..

    walterrwu 評論0 收藏0
  • 深入理解js引擎的執(zhí)行機制

    摘要:深入理解引擎的執(zhí)行機制最近在反省,很多知識都是只會用,不理解底層的知識。在閱讀之前,請先記住兩點是單線程語言的是的執(zhí)行機制。所以,是存在異步執(zhí)行的,比如單線程是怎么實現(xiàn)異步的場景描述通過事件循環(huán),所以說,理解了機制,也就理解了的執(zhí)行機制啦。 深入理解js引擎的執(zhí)行機制 最近在反省,很多知識都是只會用,不理解底層的知識。所以在開發(fā)過程中遇到一些奇怪的比較難解決的bug,在思考的時候就會收...

    feng409 評論0 收藏0
  • 談?wù)?/em> javascript 面向?qū)ο?em>的一些細節(jié)問題

    摘要:同時,創(chuàng)建的子類有幾個固定字段,分別是初始化函數(shù)原型初始化函數(shù)對象通過這個函數(shù),把基類和子類的函數(shù)合并執(zhí)行,這樣解決了基類構(gòu)造函數(shù)無法執(zhí)行的問題。二是構(gòu)造函數(shù)可能不止會操作,還可能會修改全局的某些狀態(tài)比如計數(shù)器。 綜述 在 ES6 之前,ES5 實現(xiàn)面向?qū)ο笫谴蠹医?jīng)常討論的問題,趁著 ES6 還沒進入瀏覽器,借我自己的一段腳本,跟大家討論一下 js 面向?qū)ο蟮囊恍┘毠?jié)問題,歡迎留言指教...

    newsning 評論0 收藏0
  • 計算機常識 - 收藏集 - 掘金

    摘要:使用簡記后端掘金全稱為即消息隊列。優(yōu)測優(yōu)社區(qū)干貨精選老司機亂談編輯器之神掘金前言是一種信仰,我自從年有了這個信仰,已經(jīng)個年頭了。 PHP 程序員進階學(xué)習(xí)書籍參考指南 - 后端 - 掘金PHP程序員進階學(xué)習(xí)書籍參考指南 @heiyeluren lastmodify: 2016/2/18 ... 當(dāng)我們在談?wù)撉岸思用軙r,我們在談些什么 - 前端 - 掘金潘建旭,豈安科技(www.bigse...

    Yi_Zhi_Yu 評論0 收藏0

發(fā)表評論

0條評論

frontoldman

|高級講師

TA的文章

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