成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

拔開云霧見明月 透析JavaScript定時機制

開發 前端
很多開發者在使用JavaScript定時機制時,會陷入很多誤區。文章用實際案例分析了JavaScript定時機制的原理,希望對您有所幫助。

JavaScript的setTimeout與setInterval是兩個很容易欺騙“別人感情”的方法,因為我們開始常常以為調用了就會按既定的方式執行, 我想不少人都深有同感, 例如:

51CTO推薦閱讀:JavaScript語法中12個需要繞開的陷阱

  1. setTimeout( function(){ alert(’你好!’); } , 0);  
  2. setInterval( callbackFunction , 100); 

認為setTimeout中的問候方法會立即被執行,因為這并不是憑空而說,而是JavaScript API文檔明確定義第二個參數意義為隔多少毫秒后,回調方法就會被執行. 這里設成0毫秒,理所當然就立即被執行了。同理對setInterval的callbackFunction方法每間隔100毫秒就立即被執行深信不疑!但隨著JavaScript應用開發經驗不斷的增加和豐富,有一天你發現了一段怪異的代碼而百思不得其解:

  1. div.onclick = function(){  
  2. setTimeout( function()  
  3. {document.getElementById(’inputField’).focus();}, 0);  
  4. }; 

既然是0毫秒后執行,那么還用setTimeout干什么, 此刻, 堅定的信念已開始動搖,直到最后某一天 , 你不小心寫了一段糟糕的代碼:

  1. setTimeout( function(){ while(true){} } , 100);  
  2. setTimeout( function(){ alert(’你好!’); } , 200);  
  3. setInterval( callbackFunction , 200); 

第一行代碼進入了死循環,但不久你就會發現,第二,第三行并不是預料中的事情,alert問候未見出現,callbacKFunction也杳無音訊!這時你徹底迷惘了,這種情景是難以接受的,因為改變長久以來既定的認知去接受新思想的過程是痛苦的,但情事實擺在眼前,對JavaScript真理的探求并不會因為痛苦而停止,下面讓我們來展開JavaScript線程和定時器探索之旅!

出現上面所有誤區的最主要一個原因是:潛意識中認為,JavaScript引擎有多個線程在執行,JavaScript的定時器回調函數是異步執行的,而事實上的,JavaScript使用了障眼法,在多數時候騙過了我們的眼睛,這里背光得澄清一個事實:

JavaScript引擎是單線程運行的,瀏覽器無論在什么時候都只且只有一個線程在運行JavaScript程序.

JavaScript引擎用單線程運行也是有意義的,單線程不必理會線程同步這些復雜的問題,問題得到簡化.那么單線程的JavaScript引擎是怎么配合瀏覽器內核處理這些定時器和響應瀏覽器事件的呢?下面結合瀏覽器內核處理方式簡單說明。

瀏覽器內核實現允許多個線程異步執行,這些線程在內核制控下相互配合以保持同步.假如某一瀏覽器內核的實現至少有三個常駐線 程:javascript引擎線程,界面渲染線程,瀏覽器事件觸發線程,除些以外,也有一些執行完就終止的線程,如Http請求線程,這些異步線程都會產 生不同的異步事件,下面通過一個圖來闡明單線程的JavaScript引擎與另外那些線程是怎樣互動通信的.雖然每個瀏覽器內核實現細節不同,但這其中的調用原理都是大同小異.

瀏覽器內核

由圖可看出,瀏覽器中的JavaScript引擎是基于事件驅動的,這里的事件可看作是瀏覽器派給它的各種任務,這些任務可以源自 JavaScript引擎當前執行的代碼塊,如調用setTimeout添加一個任務,也可來自瀏覽器內核的其它線程,如界面元素鼠標點擊事件,定時觸發器時間到達通知,異步請求狀態變更通知等.從代碼角度看來任務實體就是各種回調函數,JavaScript引擎一直等待著任務隊列中任務的到來.由于單線 程關系,這些任務得進行排隊,一個接著一個被引擎處理.

上圖t1-t2..tn表示不同的時間點,tn下面對應的小方塊代表該時間點的任務,假設現在是t1時刻,引擎運行在t1對應的任務方塊代碼內,在這個時間點內,我們來描述一下瀏覽器內核其它線程的狀態.

#p#

t1時刻:

◆GUI渲染線程:

該線程負責渲染瀏覽器界面HTML元素,當界面需要重繪(Repaint)或由于某種操作引發回流(reflow)時,該線程就會執行.本文雖然重 點解釋JavaScript定時機制,但這時有必要說說渲染線程,因為該線程與JavaScript引擎線程是互斥的,這容易理解,因為 JavaScript腳本是可操縱DOM元素,在修改這些元素屬性同時渲染界面,那么渲染線程前后獲得的元素數據就可能不一致了.

在JavaScript引擎運行腳本期間,瀏覽器渲染線程都是處于掛起狀態的,也就是說被”凍結”了.所以,在腳本中執行對界面進行更新操作,如添加結點,刪除結點或改變結點的外觀等更新并不會立即體現出來,這些操作將保存在一個隊列中,待JavaScript引擎空閑時才有機會渲染出來.

◆GUI事件觸發線程:

JavaScript腳本的執行不影響html元素事件的觸發,在t1時間段內,首先是用戶點擊了一個鼠標鍵,點擊被瀏覽器事件觸發線程捕捉后形成 一個鼠標點擊事件,由圖可知,對于JavaScript引擎線程來說,這事件是由其它線程異步傳到任務隊列尾的,由于引擎正在處理t1時的任務,這個鼠標 點擊事件正在等待處理.

◆定時觸發線程:

注意這里的瀏覽器模型定時計數器并不是由JavaScript引擎計數的,因為JavaScript引擎是單線程的,如果處于阻塞線程狀態就計不了時,它必須依賴外部來計時并觸發定時,所以隊列中的定時事件也是異步事件.

由圖可知,在這t1的時間段內,繼鼠標點擊事件觸發后,先前已設置的setTimeout定時也到達了,此刻對JavaScript引擎來說,定時觸發線程產生了一個異步定時事件并放到任務隊列中, 該事件被排到點擊事件回調之后,等待處理.同理, 還是在t1時間段內,接下來某個setInterval定時器也被添加了,由于是間隔定時,在t1段內連續被觸發了兩次,這兩個事件被排到隊尾等待處理.

可見,假如時間段t1非常長,遠大于setInterval的定時間隔,那么定時觸發線程就會源源不斷的產生異步定時事件并放到任務隊列尾而不管它 們是否已被處理,但一旦t1和最先的定時事件前面的任務已處理完,這些排列中的定時事件就依次不間斷的被執行,這是因為,對于JavaScript引擎來 說,在處理隊列中的各任務處理方式都是一樣的,只是處理的次序不同而已.

t1過后,也就是說當前處理的任務已返回,JavaScript引擎會檢查任務隊列,發現當前隊列非空,就取出t2下面對應的任務執行,其它時間依此類推,由此看來:如果隊列非空,引擎就從隊列頭取出一個任務,直到該任務處理完,即返回后引擎接著運行下一個任務,在任務沒返回前隊列中的其它任務是沒法被執行的.

相信您現在已經很清楚JavaScript是否可多線程,也了解理解JavaScript定時器運行機制了,下面我們來對一些案例進行分析:

案例1:setTimeout與setInterval

  1. setTimeout(function(){   /* 代碼塊... */     
  2. setTimeout(arguments.callee, 10);}, 10);  
  3. setInterval(function(){   /*代碼塊... */ }, 10); 

這兩段代碼看一起效果一樣,其實非也,第一段中回調函數內的setTimeout是JavaScript引擎執行后再設置新的setTimeout 定時, 假定上一個回調處理完到下一個回調開始處理為一個時間間隔,理論兩個setTimeout回調執行時間間隔>=10ms .第二段自setInterval設置定時后,定時觸發線程就會源源不斷的每隔十秒產生異步定時事件并放到任務隊列尾,理論上兩個setInterval 回調執行時間間隔<=10.

案例2:Ajax異步請求是否真的異步?

很多同學朋友搞不清楚,既然說JavaScript是單線程運行的,那么XMLHttpRequest在連接后是否真的異步?其實請求確實是異步的,不過這請求是由瀏覽器新開一個線程請求。

當請求的狀態變更時,如果先前已設置回調,這異步線程就產生狀態變更事件放到 JavaScript引擎的處理隊列中等待處理,當任務被處理時,JavaScript引擎始終是單線程運行回調函數,具體點即還是單線程運行onreadystatechange所設置的函數.

【編輯推薦】

  1. JavaScript中的函數式編程實踐
  2. 深入解讀JavaScript中BOM和DOM
  3. 揭開Javascript閉包的真實面目
  4. 詳解Javascript框架中的全局變量
  5. 詳解Javascript中checkbox樹的功能
責任編輯:王曉東 來源: 百度空間
相關推薦

2011-06-28 09:37:15

phpMyAdminMySQL

2018-07-25 11:08:38

新華三鷹視網絡

2022-07-14 08:36:28

NacosApollo長輪詢

2014-11-05 15:38:28

無線傲天動聯

2012-06-12 09:21:53

JavaScript

2010-09-06 10:56:54

2018-01-03 12:23:15

云計算邊緣計算

2016-09-19 14:09:52

戴爾

2009-08-28 09:43:05

C#事件

2009-09-10 10:37:19

服務器維護

2010-11-03 15:52:55

數據倉庫

2009-10-13 14:51:00

CCIE考試

2010-07-23 09:37:06

云計算本質服務

2010-01-18 09:39:25

C++語言

2010-01-19 14:28:41

C++ main()函

2010-01-22 13:45:36

C++代碼

2009-06-12 14:31:59

Google WaveGoogle Wave

2015-05-25 09:10:22

Intel

2010-10-14 10:54:09

企業無線局域網

2011-08-24 13:51:56

JavaScript
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品成人国产乱一区 | 欧美成人免费在线视频 | 国产精品视频在线观看 | 国产成人精品一区二区三区四区 | 伊人网站在线 | 久久伊人精品一区二区三区 | 99re在线免费视频 | 免费在线观看成年人视频 | 在线不卡 | 一区二区久久电影 | 黄色一级大片在线免费看产 | 中文日韩在线 | 视频在线观看一区 | 欧美成人免费 | 国产精品高清一区二区 | 在线一区二区观看 | 一级一级毛片免费看 | 免费视频一区二区 | 国产在线中文字幕 | 国产一区二区三区四区 | 欧美精品一区二区三区视频 | 日韩欧美精品 | 欧美国产视频一区二区 | 国产成人精品综合 | 超碰网址 | 国产亚洲精品久久久久动 | 毛片免费在线观看 | 国产精品免费一区二区三区四区 | 成人精品一区二区 | 久久亚洲高清 | 成人视屏在线观看 | 国产午夜精品一区二区三区四区 | 黑人精品 | 成人免费在线播放视频 | 亚洲精品视频在线观看免费 | 一区二区三区四区电影视频在线观看 | 欧美在线视频一区二区 | 国产精品一区二区三区四区 | 亚洲日本国产 | 欧美国产精品一区二区三区 | 性大毛片视频 |