摘要:是的,沒錯是單線程的,但是會另開一個線程,這個線程依賴于某個計時裝置,這時,其實是不管而繼續(xù)往下進行的,而也是獨立的線程計時的。
setTimeout的運行機制
先看下面一個例子:
這個代碼會讓瀏覽器陷入崩潰,為什么?
其實:
當javascript運行時遇到setTimeout后其實會另開一條線程(剛剛不是說javascript是單線程的嘛?)。是的,沒錯javascript是單線程的,但是setTimeout會另開一個線程,這個線程依賴于某個計時裝置,這時,javascript其實是不管setTimeout而繼續(xù)往下進行的,而setTimeout也是獨立的線程計時的。而javascript在運行完全部的代碼后會回過頭來重新檢測自己的隊列中有沒待執(zhí)行的命令或者函數(shù),如果有就執(zhí)行,沒有就等待。直到有待執(zhí)行的命令被加載進這個隊列中然后執(zhí)行。在這期間,setTimeout依賴的那個計時線程如果時間到了,那么它會把setTimeout中要執(zhí)行的函數(shù)或者命令傳送到j(luò)avascript的等待隊列中,等待javascript執(zhí)行完命令后回頭來檢測等待隊列中未執(zhí)行的函數(shù)或命令。
所以,在這里案例中,首先t變成true,然后javascript往下執(zhí)行,遇到了setTimeout,這時setTimeout啟用了另一個計時線程。此時javascript不管它跳過(因為它由另一個線程來控制)。然后遇到了while(t)這個循環(huán),因為前面把t設(shè)置成了真,所以這個循環(huán)一直成立,所以也就一直循環(huán)下去。javascript的線程一直結(jié)束不了,所以無法回來檢查等待隊列,根本不會執(zhí)行setTimeout中代碼。所以t永遠也無法變成假,而javascript也永遠無法停止。
了解了setTimeout的運行機制后 我們來看看幾個setTimeout并列運行 它們的執(zhí)行順序由什么決定
setTimeout(function(){ console.log(3); },5000); setTimeout(function(){ console.log(5); },3000); setTimeout(function(){ console.log(6); },14000);
結(jié)果是5,3,6。幾個都是setTimeout,因此都會放到等待隊列~~~
而這些隊列里的函數(shù)誰先執(zhí)行呢?就是根據(jù)setTimeout里的第二個參數(shù)(延遲時間)決定的。
再看看一個復(fù)雜的例子 如果setTimeout中嵌套了setTimeout 呢?
var d=[]; d[0]=function(){setTimeout(function(){console.log(3);setTimeout(function(){console.log(4)})})}; d[1]=function(){setTimeout(function(){console.log(5);setTimeout(function(){console.log(6)},0)},100)}; for(var i=0;i<2;i++){d[i]();}
這段代碼 按順序打印的是 3,4,5,6 實際上是這樣 主程序執(zhí)行完后 遇到了兩個settimeout函數(shù) 第一個是0毫秒,第二是100毫秒 先執(zhí)行第一個settimeout,打印出3,
第一個函數(shù)執(zhí)行的時候又遇見了一個settimeout 加入隊列 等待時間是0,打印出了4,登到了100毫秒后 第二個settimeout被執(zhí)行 打印出5.又遇見一個settimeout,同樣被加入隊列 等了0毫秒 被執(zhí)行
再換換數(shù)據(jù)試一試:
var d=[];d[0]=function(){setTimeout(function(){console.log(3);setTimeout(function(){console.log(4)})})}; d[1]=function(){setTimeout(function(){console.log(5);setTimeout(function(){console.log(6)})},2)}; for(var i=0;i<2;i++){d[i]();}
這里的時間相差極短 打印出的順序是3,5,4,6
如果再換一下數(shù)據(jù):
var d=[];d[0]=function(){setTimeout(function(){console.log(3);setTimeout(function(){console.log(4)})})}; d[1]=function(){setTimeout(function(){console.log(5);setTimeout(function(){console.log(6)})},4)}; for(var i=0;i<2;i++){d[i]();}
這里相比上面的案例只是改了一個數(shù)字 2毫秒改成了4毫秒 執(zhí)行順序變成 3,4,5,6
為什么?
因為上面的案例執(zhí)行完第一個settimeout之后 過了2毫秒了 超過了第二個函數(shù)的等待時間 會立即執(zhí)行第二個settimeout。如果等待時間過大 就不會這樣了
總之,只需記住一點:延遲時間始終是相對主程序執(zhí)行完畢的那個時間算的 ,并且多個setTimeout的先后順序也是由這個延遲時間決定的,如果遇到某個setTimeout需要花費大量的時間怎么辦?可由于js是單線程,所以當執(zhí)行到這個setTimeout后,會將這個程序執(zhí)行完成后再去執(zhí)行下一個setTimeout,無論下一個setTimeout的延遲時間為多少,如果這兩個setTimeout時間的差值小于第一個setTimeout消耗的時間,程序會等待這個setTimeout執(zhí)行完成后立即執(zhí)行下一個setTimeout,如果差值大于消耗的時間,就按照和主程序約定的延遲(setTimeout里的第二個參數(shù))執(zhí)行即可
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/84331.html
摘要:如果對語法分析和預(yù)編譯,還有疑問引擎執(zhí)行的過程的理解語法分析和預(yù)編譯階段。參與執(zhí)行過程的線程分別是引擎線程也稱為內(nèi)核,負責(zé)解析執(zhí)行腳本程序的主線程例如引擎。以上便是引擎執(zhí)行宏任務(wù)的整個過程。 一、概述 js引擎執(zhí)行過程主要分為三個階段,分別是語法分析,預(yù)編譯和執(zhí)行階段,上篇文章我們介紹了語法分析和預(yù)編譯階段,那么我們先做個簡單概括,如下: 1、語法分析: 分別對加載完成的代碼塊進行語法...
摘要:如果對語法分析和預(yù)編譯,還有疑問引擎執(zhí)行的過程的理解語法分析和預(yù)編譯階段。參與執(zhí)行過程的線程分別是引擎線程也稱為內(nèi)核,負責(zé)解析執(zhí)行腳本程序的主線程例如引擎。以上便是引擎執(zhí)行宏任務(wù)的整個過程。一、概述 js引擎執(zhí)行過程主要分為三個階段,分別是語法分析,預(yù)編譯和執(zhí)行階段,上篇文章我們介紹了語法分析和預(yù)編譯階段,那么我們先做個簡單概括,如下: 1、語法分析: 分別對加載完成的代碼塊進行語法檢驗,語...
摘要:曾經(jīng)的理解首先,是單線程語言,也就意味著同一個時間只能做一件事,那么為什么不是多線程呢這樣還能提高效率啊假定同時有兩個線程,一個線程在某個節(jié)點上編輯了內(nèi)容,而另一個線程刪除了這個節(jié)點,這時瀏覽器就很懵逼了,到底以執(zhí)行哪個操作呢所以,設(shè)計者把 Event Loop曾經(jīng)的理解 首先,JS是單線程語言,也就意味著同一個時間只能做一件事,那么 為什么JavaScript不是多線程呢?這樣還能提...
摘要:一個頁面在瀏覽器顯示出來至少需要個線程,分別是引擎,渲染,事件觸發(fā)。其中事件觸發(fā)是獨立于其他個執(zhí)行的,而和是相互排斥的,也就是說同一個時間二者只有一個在工作。 作為DOM本身十分重要的2個異步執(zhí)行函數(shù),初學(xué)者感覺這個很不好理解,我簡單寫一寫我的理解 setTimeout (func, millisec); setInterval(func, millisec); 這兩個方法在形式看起來...
摘要:所以其實和所謂的異步調(diào)用事實上是通過將代碼段插入到代碼的執(zhí)行隊列中實現(xiàn)的。當執(zhí)行和的時候,會根據(jù)你設(shè)定的時間準確地找到代碼的插入點。綜上所述,其實終歸是單線程產(chǎn)物。無論如何異步都不可能突破單線程這個障礙。 發(fā)表過一片博客《跟著我用JavaScript寫計時器》,比較基礎(chǔ).....有網(wǎng)友說應(yīng)該寫一下setTimeout的原理和機制,嗯,今天就來寫一下吧: 直奔主題:setTimeout和...
閱讀 3327·2023-04-26 00:58
閱讀 1278·2021-09-22 16:04
閱讀 3324·2021-09-02 15:11
閱讀 1572·2019-08-30 15:55
閱讀 2349·2019-08-30 15:55
閱讀 3281·2019-08-23 18:41
閱讀 3472·2019-08-23 18:18
閱讀 2760·2019-08-23 17:53