欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

理解javascript定時器中的單線程

 更新時間:2016年02月23日 11:44:02   投稿:lijiao  
這篇文章主要幫助大家理解javascript定時器中的單線程,感興趣的小伙伴們可以參考一下

一、JavaScript 引擎是單線程的

可以從下面的代碼中看到,第一個用setTimeout中的代碼是死循環(huán),由于是單線程,下面的兩個定時器就沒機會執(zhí)行了。

<script type="text/javascript">
 setTimeout( function(){ while(true){} } , 100); 
 setTimeout( function(){ alert('你好!setTimeout'); } , 200); 
 setInterval( function(){ alert('你好!setInterval'); } , 200); 
</script>

瀏覽器的內(nèi)核是多線程的,它們在內(nèi)核制控下相互配合以保持同步,一個瀏覽器至少實現(xiàn)3個常駐線程:javascript引擎線程,GUI渲染線程,瀏覽器事件觸發(fā)線程。

JavaScript引擎是基于事件驅(qū)動單線程執(zhí)行的,JS引擎一直等待著任務(wù)隊列中任務(wù)的到來然后加以處理,瀏覽器無論再什么時候都只有一個JS線程在運行JS程序。
GUI渲染線程負責(zé)渲染瀏覽器界面,當界面需要重繪(Repaint)或由于某種操作引發(fā)回流(reflow)時,該線程就會執(zhí)行。但需要注意 GUI渲染線程與JS引擎是互斥的,當JS引擎執(zhí)行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JS引擎空閑時立即被執(zhí)行。
瀏覽器事件觸發(fā)線程,當一個事件被觸發(fā)時該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理。這些事件可來自JavaScript引擎當前執(zhí)行的代碼塊如setTimeOut、也可來自瀏覽器內(nèi)核的其他線程如鼠標點擊、AJAX異步請求等,但由于JS的單線程關(guān)系所有這些事件都得排隊等待JS引擎處理。

  由上圖可看出,瀏覽器中的JavaScript引擎是基于事件驅(qū)動的,這里的事件可看作是瀏覽器派給它的各種任務(wù),JavaScript引擎一直等待著任務(wù)隊列中任務(wù)的到來,由于單線程關(guān)系,這些任務(wù)得進行排隊,一個接著一個被引擎處理。

t1、t2....tn表示不同的時間點,tn下面對應(yīng)的小方塊代表該時間點的任務(wù)。

t1時刻:

1、GUI渲染線程
2、瀏覽器事件觸發(fā)線程:

在t1時間段內(nèi),首先是用戶點擊了一個鼠標鍵,點擊被瀏覽器事件觸發(fā)線程捕捉后形成一個鼠標點擊事件,由圖可知,對于JavaScript引擎線程來說,這事件是由其它線程異步傳到任務(wù)隊列尾的,由于引擎正在處理t1時的任務(wù),這個鼠標點擊事件正在等待處理。
3、定時觸發(fā)線程:
這里的瀏覽器模型定時計數(shù)器并不是由JavaScript引擎計數(shù)的,因為JavaScript引擎是單線程的,如果處于阻塞線程狀態(tài)就計不了時,它必須依賴外部來計時并觸發(fā)定時,所以隊列中的定時事件是異步事件。
4、在這t1的時間段內(nèi),繼鼠標點擊事件觸發(fā)后,先前已設(shè)置的setTimeout定時也到達了,此刻對JavaScript引擎來說,定時觸發(fā)線程產(chǎn)生了一個異步定時事件并放到任務(wù)隊列中,該事件被排到點擊事件回調(diào)之后,等待處理。同理,還是在t1時間段內(nèi),接下來某個setInterval定時器也被添加了,由于是間隔定時,在t1段內(nèi)連續(xù)被觸發(fā)了兩次,這兩個事件被排到隊尾等待處理。
5、ajax異步請求:
瀏覽器新開一個http線程請求,當請求的狀態(tài)變更時,如果先前已設(shè)置回調(diào),這異步線程就產(chǎn)生狀態(tài)變更事件放到JavaScript引擎的處理隊列中等待處理。
二、任務(wù)的執(zhí)行順序不同,顯示結(jié)果也不同

1)未使用setTimeout函數(shù)

在網(wǎng)上找到的一段代碼實例,這里用來演示一下。

<a href="#" id="doBtn">do something</a>
<div id="status"></div>
<script type="text/javascript">
  var doBtn = document.getElementById('doBtn')
   , status = document.getElementById('status');

  function sleep(ms) {
  var start = new Date();
  while (new Date() - start <= ms) {}
  }
  
  doBtn.onclick = function(e) {
   status.innerHTML = 'doing...please wait...'; 
   sleep(3000); // 模擬一個耗時較長的計算過程,3s
   status.innerHTML = 'done'; 
   return false;
  };
</script>

我在firefox中執(zhí)行了上面的代碼。計劃是點擊“do something”按鈕,然后顯示“doing...please wait...”,接著執(zhí)行sleep,最后顯示“done”。

但是結(jié)果是點擊后,瀏覽器卡住3秒左右,最后直接顯示done。

分析下看出,在做status.innerHTML設(shè)置的時候,是需要執(zhí)行GUI渲染線程的,但是現(xiàn)在還在執(zhí)行JavaScript引擎線程,而JavaScript引擎線程與GUI渲染線程是互斥的,所以就最后顯示了done。

 2)使用了setTimeout函數(shù)

<a href="#" id="doBtn2">do something timer</a>
<div id="status2"></div>
<script type="text/javascript">
  var doBtn2 = document.getElementById('doBtn2')
   , status2 = document.getElementById('status2');

  function sleep2(ms) {
  var start = new Date();
  while (new Date() - start <= ms) {}
  }
  
  doBtn2.onclick = function(e) {
   status2.innerHTML = 'doing...please wait...'; 
   setTimeout(function() {
   sleep2(3000); 
   status2.innerHTML = 'done'; 
   }, 100); 
   return false;
  };
</script>

在“doing...please wait...”后面加了個setTimeout,延時執(zhí)行,給了瀏覽器渲染的時間,這個時候會顯示出“doing...please wait...”的字樣,然后執(zhí)行sleep函數(shù),最后顯示“done”。

后面有網(wǎng)友發(fā)現(xiàn)在firefox中不起作用,的確有這個問題,后面我修改了一下代碼,將局部變量的聲明,onclick的綁定放到了window.onload事件中,等頁面結(jié)構(gòu)加載完成后,我再做腳本操作。

<script type="text/javascript">
  function sleep(ms) {
  //...
  }
  window.onload = function() {
   var doBtn = document.getElementById('doBtn'),
   status = document.getElementById('status');
   
   var doBtn2 = document.getElementById('doBtn2')
    , status2 = document.getElementById('status2');
    
   doBtn.onclick = function(e) {
    //...
   };
   doBtn2.onclick = function(e) {
    //...
   };
  };
</script>

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • Textarea與懶惰渲染實現(xiàn)代碼

    Textarea與懶惰渲染實現(xiàn)代碼

    2008年有啊第一次性能優(yōu)化時,我們曾用textarea來存貯需要懶惰渲染的節(jié)點
    2012-01-01
  • 基于javascript的無縫滾動動畫實現(xiàn)2

    基于javascript的無縫滾動動畫實現(xiàn)2

    這篇文章主要介紹了基于javascript的無縫滾動動畫實現(xiàn)2,文章通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • JS+cookie實現(xiàn)購物評價五星好評功能

    JS+cookie實現(xiàn)購物評價五星好評功能

    這篇文章主要為大家詳細介紹了JS+cookie實現(xiàn)購物評價五星好評功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • three.js中多線程的使用及性能測試詳解

    three.js中多線程的使用及性能測試詳解

    這篇文章主要給大家介紹了關(guān)于three.js中多線程的使用及性能測試的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 基于JavaScript實現(xiàn)文件共享型網(wǎng)站

    基于JavaScript實現(xiàn)文件共享型網(wǎng)站

    Any?Share?是一種簡單、輕量、快速的文件共享服務(wù)。使用?Javascript?編寫,并搭建在?Firebase?平臺。本文將利用它實現(xiàn)創(chuàng)建文件共享型網(wǎng)站,感興趣的可以了解一下
    2022-11-11
  • 使用javascript函數(shù)編寫簡單銀行取錢存錢流程

    使用javascript函數(shù)編寫簡單銀行取錢存錢流程

    本文通過實例代碼給大家講解了使用javascript函數(shù)編寫簡單銀行取錢存錢流程,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2018-05-05
  • js中apply()和call()的區(qū)別與用法實例分析

    js中apply()和call()的區(qū)別與用法實例分析

    這篇文章主要介紹了js中apply()和call()的區(qū)別與用法,結(jié)合實例形式分析了apply()和call()的功能、區(qū)別、使用方法及相關(guān)操作注意事項,需要的朋友可以參考下
    2018-08-08
  • 微信小程序在text文本實現(xiàn)多種字體樣式

    微信小程序在text文本實現(xiàn)多種字體樣式

    這篇文章主要介紹了微信小程序在text文本實現(xiàn)多種字體樣式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • JavaScript截取字符串的Slice、Substring、Substr函數(shù)詳解和比較

    JavaScript截取字符串的Slice、Substring、Substr函數(shù)詳解和比較

    這篇文章主要介紹了JavaScript截取字符串的Slice、Substring、Substr函數(shù)詳解和比較,需要的朋友可以參考下
    2014-03-03
  • 微信小程序如何加載數(shù)據(jù)庫真實數(shù)據(jù)的實現(xiàn)

    微信小程序如何加載數(shù)據(jù)庫真實數(shù)據(jù)的實現(xiàn)

    這篇文章主要介紹了微信小程序如何加載數(shù)據(jù)庫真實數(shù)據(jù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03

最新評論