日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[译]理解js中的event loop

發(fā)布時(shí)間:2025/6/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [译]理解js中的event loop 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

之前看的文,感覺(jué)不太完整,于是找了篇詳細(xì)的文章原文鏈接。翻譯不正確的請(qǐng)指出,重在分享,如果有所收獲就更好了。

Javascript是如何異步和單線程的?簡(jiǎn)短的回答是javascript語(yǔ)言是單線程的,異步行為不是它的一部分,相反,它是建立在瀏覽器(或編程環(huán)境)中的核心JavaScript語(yǔ)言之上,并通過(guò)瀏覽器API訪問(wèn)。

現(xiàn)在為了得到答案,讓我寫(xiě)兩個(gè)示例代碼片段。

基本架構(gòu)

  • :對(duì)象在堆中分配,表示大多數(shù)非結(jié)構(gòu)化的內(nèi)存區(qū)域。
  • :這表示JavaScript代碼執(zhí)行提供的單個(gè)線程,函數(shù)調(diào)用形成一個(gè)棧。
  • 瀏覽器或Web API是內(nèi)置在你的web瀏覽器中,能夠暴露瀏覽器和周?chē)挠?jì)算機(jī)環(huán)境中的數(shù)據(jù),并使用它執(zhí)行游泳的復(fù)雜操作。它們不是JavaScript語(yǔ)言的一部分,而是基于核心JavaScript語(yǔ)言構(gòu)建,為你的JavaScript代碼中提供額外的超能力。例如,Geolocation API提供了一些簡(jiǎn)單的JavaScript構(gòu)造,用于檢索數(shù)據(jù),所以你可以說(shuō),在Google map上繪制你的位置。在后臺(tái),瀏覽器實(shí)際上使用一些復(fù)雜的低級(jí)代碼(例如C++)與設(shè)備的GPS硬件(或者任何可用于確定位置數(shù)據(jù)的信息)進(jìn)行通信,檢索位置數(shù)據(jù),并將其返回到瀏覽器環(huán)境用來(lái)使用在你的代碼中。但同樣,這種復(fù)雜性是由API抽象出來(lái)的。

代碼片段1:迷惑心靈

function main(){console.log('A');setTimeout(function display(){ console.log('B'); },0);console.log('C'); } main(); // Output // A // C // B 復(fù)制代碼

這里,我們有一個(gè)主函數(shù),它有兩個(gè)console.log:將A和C輸入到控制臺(tái)上。它們中間是一個(gè)在0ms后將B輸出到控制臺(tái)上的setTimeOut調(diào)用。

  • 調(diào)用主函數(shù),首先將它推入到棧中。然后瀏覽器將主函數(shù)的第一個(gè)聲明console.log('A')推入到棧中,執(zhí)行此語(yǔ)句,并在完成后彈出,字母A顯示在控制臺(tái)上。
  • 第二個(gè)聲明setTimeout推入棧中并開(kāi)始執(zhí)行。setTimeout函數(shù)使用瀏覽器的API來(lái)延遲回調(diào)其中的函數(shù)。一旦交接給brower完成timer,這一幀就被推出。
  • 當(dāng)計(jì)時(shí)器在瀏覽器中運(yùn)行來(lái)回調(diào)exec函數(shù)時(shí),console.log(‘C’)被推入棧中。在這種特殊的情況下,由于提供的延遲是0ms,一旦瀏覽器接收到它(理想情況下),回調(diào)將被添加到消息隊(duì)列中。
  • 執(zhí)行完主函數(shù)的最后一個(gè)語(yǔ)句,主函數(shù)從調(diào)用堆棧中彈出,從而堆棧為空。對(duì)于瀏覽器將任何消息從隊(duì)列推送到調(diào)用堆棧中,調(diào)用堆棧必須為空。這就是為什么即使setTimeout中提供的延遲是0ms,exec的也必須等到調(diào)用堆棧中的所有幀的執(zhí)行完成。
  • 現(xiàn)在exec的回調(diào)被推入調(diào)用棧,接著執(zhí)行。字母C顯示在控制臺(tái)上。這就是JavaScript的事件循環(huán)。
  • 因此setTimeout(function,delayTime)中的delay參數(shù)不代表執(zhí)行函數(shù)之后的精確時(shí)間延遲。它代表最小等待時(shí)間,之后在某個(gè)時(shí)間點(diǎn)執(zhí)行該功能。

    代碼片段2:深入理解

    function main(){console.log('A');setTimeout(function exec(){ console.log('B'); }, 0);runWhileLoopForNSeconds(3);console.log('C'); } main(); function runWhileLoopForNSeconds(sec){let start = Date.now(), now = start;while (now - start < (sec*1000)) {now = Date.now();} } // Output // A // C // B 復(fù)制代碼

    • 函數(shù)runWhileLoopForNSeconds完全符合其名稱所代表的含義,它會(huì)不斷檢查從調(diào)用時(shí)間開(kāi)始經(jīng)過(guò)的時(shí)間是否等于函數(shù)參數(shù)提供的秒數(shù)。要記住的要點(diǎn)是while循環(huán)(與許多其他循環(huán)一樣)是一個(gè)阻塞語(yǔ)句,意味著它的執(zhí)行發(fā)生在調(diào)用堆棧上,并且不使用瀏覽器API。因此它會(huì)阻止所有后續(xù)語(yǔ)句,直到它執(zhí)行完成。
    • 所以在上面的代碼中,即使setTimeout的延遲為0ms,但在while循環(huán)運(yùn)行3s中,exec()回調(diào)會(huì)卡在消息隊(duì)列中。只有在while循環(huán)在調(diào)用堆棧(單線程)上運(yùn)行3s完成,調(diào)用堆棧變空之后,回調(diào)exec()被推入到調(diào)用堆棧并執(zhí)行。
    • 因此setTimeout()中的delay參數(shù)不保證在計(jì)時(shí)器完成延遲后開(kāi)始執(zhí)行。它是延遲部分的最短時(shí)間。

    總結(jié)

    以上是生活随笔為你收集整理的[译]理解js中的event loop的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。