最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

javascript異步處理工作機制詳解

 更新時間:2015年04月13日 09:43:54   投稿:hebedich  
籠統(tǒng)地說,異步在javascript就是延時執(zhí)行。嚴格來說,javascript中的異步編程能力都是由BOM與DOM提供的,如setTimeout,XMLHttpRequest,還有DOM的事件機制,等等很多。這些東西都有一個共同的特點,就是擁有一個回調函數,實現控制反轉。

從基礎的層面來講,理解JavaScript的定時器是如何工作的是非常重要的。計時器的執(zhí)行常常和我們的直觀想象不同,那是因為JavaScript引擎是單線程的。我們先來認識一下下面三個函數是如何控制計時器的。

var id = setTimeout(fn, delay); - 初始化一個計時器,然后在指定的時間間隔后執(zhí)行。該函數返回一個唯一的標志ID(Number類型),我們可以使用它來取消計時器。
var id = setInterval(fn, delay); - 和setTimeout有些類似,但它是連續(xù)調用一個函數(時間間隔是delay參數)直到它被取消。
clearInterval(id);, clearTimeout(id); - 使用計時器ID(setTimeout 和 setInterval的返回值)來取消計時器回調的發(fā)生
為了理解計時器的內在執(zhí)行原理,有一個重要的概念需要加以探討:計時器的延遲(delay)是無法得到保障的。由于所有JavaScript代碼是在一個線程里執(zhí)行的,所有異步事件(例如,鼠標點擊和計時器)只有擁有執(zhí)行機會時才會執(zhí)行。

在這個圖表中有許多信息需要理解,如果完全理解了它們,你會對JavaScript引擎如何實現異步事件有一個很好的認識。這是一個一維的圖標:垂 直方向表示時間,藍色的區(qū)塊表示JavaScript代碼執(zhí)行塊。例如第一個JavaScript代碼執(zhí)行塊需要大約18ms,鼠標點擊所觸發(fā)的代碼執(zhí)行 塊需要11ms,等等。

由于JavaScript引擎同一時間只執(zhí)行一條代碼(這是由于JavaScript單線程的性質),所以每一個JavaScript代碼執(zhí)行塊會 “阻塞”其它異步事件的執(zhí)行。這就意味著當一個異步事件發(fā)生(例如,鼠標點擊,計時器被觸發(fā),或者Ajax異步請求)后,這些事件的回調函數將排在執(zhí)行隊 列的最后等待執(zhí)行(實際上,排隊的方式根據瀏覽器的不同而不同,所以這里只是一個簡化);

從第一個JavaScript執(zhí)行塊開始研究,在第一個執(zhí)行塊中兩個計時器被初始化:一個10ms的setTimeout()和一個10ms的setInterval()。 依據何時何地計時器被初始化(計時器初始化完畢后就會開始計時),計時器實際上會在第一個代碼塊執(zhí)行完畢前被觸發(fā)。但是,計時器上綁定的函數不會立即執(zhí)行 (不被立即執(zhí)行的原因是JavaScript是單線程的)。實際上,被延遲的函數將依次排在執(zhí)行隊列的最后,等待下一次恰當的時間再執(zhí)行。

此外,在第一個JavaScript執(zhí)行塊中我們看到了一個“鼠標點擊”事件發(fā)生了。一個JavaScript回調函數綁定在這個異步事件上了(我 們從來不知道用戶什么時候執(zhí)行這個(點擊)事件,因此認為它是異步的),這個函數不會被立即執(zhí)行,和上面的計時器一樣,它將排在執(zhí)行隊列的最后,等待下一 次恰當的時候執(zhí)行。

當第一個JavaScript執(zhí)行塊執(zhí)行完畢后,瀏覽器會立即問一個問題:哪個函數(語句)在等待被執(zhí)行?在這時,一個“鼠標點擊事件處理函數”和 一個“計時器回調函數”都在等待執(zhí)行。瀏覽器會選擇一個(實際上選擇了“鼠標點擊事件的處理函數”,因為由圖可知它是先進隊的)立即執(zhí)行。而“計時器回調 函數”將等待下次適合的時間執(zhí)行。

注意,當“鼠標點擊事件處理函數”執(zhí)行的時候,setInterval的回調函數第一次被觸發(fā)了。和setTimeout的回調函數一樣,它將排到執(zhí)行隊列的最后等待執(zhí)行。但是,一定要注意這一點:當setInterval回調函數第二次被觸發(fā)時(此時setTimeout函數仍在執(zhí)行)setInterval的第一次觸發(fā)將被拋棄掉。當一個很長的代碼塊在執(zhí)行時,可能把所有的setInterval回調函數都排在執(zhí)行隊列的后面,代碼塊執(zhí)行完之后,結果便會是一大串的setInterval回調函數等待執(zhí)行,并且這些函數之間沒有間隔,直到全部完成。所以,瀏覽器傾向于的當沒有更多interval的處理函數在排隊時再將下一個處理函數排到隊尾(這是由于間隔的問題)。

我們能夠發(fā)現,當第三個setInterval回調函數被觸發(fā)時,之前的setInterval回調函數仍在執(zhí)行。這就說明了一個很重要的事實:setInterval不會考慮當前正在執(zhí)行什么,而把所有的堵塞的函數排到隊列尾部。這意味著兩次setInterval回調函數之間的時間間隔會被犧牲掉(縮減)。

最后,當第二個setInterval回調函數執(zhí)行完畢后,我們可以看到沒有任何程序等待JavaScript引擎執(zhí)行了。這就意味著瀏覽器現在在等待一個新的異步事件的發(fā)生。在50ms時一個新的setInterval回調函數再次被觸發(fā),這時,沒有任何的執(zhí)行塊阻塞它的執(zhí)行了。所以它會立刻被執(zhí)行。

讓我們用一個例子來闡明setTimeout和setInterval之間的區(qū)別:

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

這兩句代碼乍一看沒什么差別,但是它們是不同的。setTimeout回調函數的執(zhí)行和上一次執(zhí)行之間的間隔至少有10ms(可能會更多,但不會少于10ms),而setInterval的回調函數將嘗試每隔10ms執(zhí)行一次,不論上次是否執(zhí)行完畢。

在這里我們學到了很多知識,總結一下:

JavaScript引擎是單線程的,強制所有的異步事件排隊等待執(zhí)行
setTimeout 和 setInterval 在執(zhí)行異步代碼的時候有著根本的不同
如果一個計時器被阻塞而不能立即執(zhí)行,它將延遲執(zhí)行直到下一次可能執(zhí)行的時間點才被執(zhí)行(比期望的時間間隔要長些)
如果setInterval回調函數的執(zhí)行時間將足夠長(比指定的時間間隔長),它們將連續(xù)執(zhí)行并且彼此之間沒有時間間隔。

以上所述就是本文的全部內容了,希望能夠對大家學習javascript異步處理有所幫助。

相關文章

  • JS實現的二叉樹算法完整實例

    JS實現的二叉樹算法完整實例

    這篇文章主要介紹了JS實現的二叉樹算法,結合完整實例形式分析了基于JS定義、創(chuàng)建二叉樹及常用的各種遍歷、訪問二叉樹操作技巧,需要的朋友可以參考下
    2017-04-04
  • JavaScript中的變量作用域介紹

    JavaScript中的變量作用域介紹

    這篇文章主要介紹了JavaScript中的變量作用域介紹,本文同時講解了一個新概念變量的作用域鏈,需要的朋友可以參考下
    2014-12-12
  • JS實現的簡單輪播圖運動效果示例

    JS實現的簡單輪播圖運動效果示例

    這篇文章主要介紹了JS實現的簡單輪播圖運動效果,結合完整實例形式分析了javascript基于定時器動態(tài)修改頁面元素屬性的相關操作技巧,需要的朋友可以參考下
    2016-12-12
  • JavaScript數組操作學習之splice()函數入門與精通

    JavaScript數組操作學習之splice()函數入門與精通

    這篇文章介紹了JavaScript數組操作中的splice()方法,詳細講解了其定義、語法和用法,并通過實例展示了如何使用該方法進行數組元素的添加、刪除和替換,需要的朋友可以參考下
    2024-11-11
  • List Information About the Binary Files Used by an Application

    List Information About the Binary Files Used by an Applicati

    List Information About the Binary Files Used by an Application...
    2007-06-06
  • js取兩個數組的交集|差集|并集|補集|去重示例代碼

    js取兩個數組的交集|差集|并集|補集|去重示例代碼

    求兩個集合的補集、交集、差集、并集等等在實際應用中經常會使用到,下面與大家分享下具體的實現代碼,感興趣的朋友可以參考下,希望對大家有所幫助
    2013-08-08
  • 利用js判斷手機是否安裝某個app的多種方案

    利用js判斷手機是否安裝某個app的多種方案

    這篇文章主要介紹了利用js檢測手機是否安裝某個app的多種方案,當判斷后如果安裝了直接打開,如果有沒有安裝將自動跳轉到下載的界面,有需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-02-02
  • layui實現點擊按鈕給table添加一行

    layui實現點擊按鈕給table添加一行

    想實現點擊按鈕在表格添加一行的功能,但發(fā)現layui并未集成該工具欄,因此,需要自己手動添加這個功能;這篇文章主要介紹了layui點擊按鈕給table添加一行,需要的朋友可以參考下
    2018-08-08
  • js實現中文實時時鐘

    js實現中文實時時鐘

    這篇文章主要為大家詳細介紹了js實現中文實時時鐘,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-01-01
  • js 獲取Listbox選擇的值的代碼

    js 獲取Listbox選擇的值的代碼

    將Listbox的 SelectionMode="Multiple",設置為多選時,用JS獲取多選的值。
    2010-04-04

最新評論

额尔古纳市| 澳门| 桃江县| 措美县| 杂多县| 墨玉县| 仙游县| 嘉黎县| 无锡市| 祁东县| 海盐县| 邻水| 公主岭市| 班戈县| 磐安县| 水富县| 保定市| 闸北区| 菏泽市| 任丘市| 咸阳市| 西畴县| 都昌县| 广东省| 丹凤县| 平乐县| 宝坻区| 福泉市| 隆安县| 五大连池市| 正镶白旗| 淳安县| 朝阳区| 吉隆县| 浦东新区| 平陆县| 洛南县| 墨竹工卡县| 正安县| 留坝县| 英山县|