亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JS代碼在nodejs環(huán)境下執(zhí)行機(jī)制和事件循環(huán)

Lowky / 2513人閱讀

摘要:開始執(zhí)行文件,同步代碼執(zhí)行完畢后,進(jìn)入事件循環(huán)。時(shí)間未到的時(shí)候,如果有事件返回,就執(zhí)行該事件注冊(cè)的回調(diào)函數(shù)。對(duì)于多次執(zhí)行輸出結(jié)果不同,需要了解事件循環(huán)的基礎(chǔ)問題。

1. 說明

nodejs是單線程執(zhí)行的,同時(shí)它又是基于事件驅(qū)動(dòng)的非阻塞IO編程模型。這就使得我們不用等待異步操作結(jié)果返回,就可以繼續(xù)往下執(zhí)行代碼。當(dāng)異步事件觸發(fā)之后,就會(huì)通知主線程,主線程執(zhí)行相應(yīng)事件的回調(diào)。

本篇文章講解node中JavaScript的代碼的執(zhí)行流程,下面是測(cè)試代碼,如果你知道輸出的結(jié)果,那么就不需要再看本篇文章,如果不知道輸出結(jié)果,那么本片文章可幫助你了解:

console.log(1)
setTimeout(function () {
  new Promise(function (resolve) {
    console.log(2)
    resolve()
  })
  .then(() => { console.log(3) })
})
setTimeout(function () {
  console.log(4)
})

復(fù)雜的:

setTimeout(() => {
  console.log("1")
  new Promise((resolve) => { console.log("2"); resolve(); })
  .then(() => { console.log("3") })
  new Promise((resolve)=> { console.log("4"); resolve()})
  .then(() => { console.log("5") })
  setTimeout(() => { 
    console.log("6")
    setTimeout(() => {
      console.log("7")
      new Promise((resolve) => { console.log("8"); resolve() })
      .then( () => {  console.log("9") })
      new Promise((resolve) => { console.log("10"); resolve() })
      .then(() => {  console.log("11") })
    })
    setTimeout(() => { console.log("12") }, 0)
  })
  setTimeout(() => { console.log("13") }, 0)
})
setTimeout(() => { console.log("14") }, 0)
new Promise((resolve) => { console.log("15"); resolve() })
.then( ()=> { console.log("16") })
new Promise((resolve) => { console.log("17"); resolve() })
.then(() => { console.log("18") })
2. nodejs的啟動(dòng)過程

node.js啟動(dòng)過程可以分為以下步驟:

調(diào)用platformInit方法 ,初始化 nodejs 的運(yùn)行環(huán)境。

調(diào)用 performance_node_start 方法,對(duì) nodejs 進(jìn)行性能統(tǒng)計(jì)。

openssl設(shè)置的判斷。

調(diào)用v8_platform.Initialize,初始化 libuv 線程池。

調(diào)用 V8::Initialize,初始化 V8 環(huán)境。

創(chuàng)建一個(gè)nodejs運(yùn)行實(shí)例。

啟動(dòng)上一步創(chuàng)建好的實(shí)例。

開始執(zhí)行js文件,同步代碼執(zhí)行完畢后,進(jìn)入事件循環(huán)。

在沒有任何可監(jiān)聽的事件時(shí),銷毀 nodejs 實(shí)例,程序執(zhí)行完畢。

3. nodejs的事件循環(huán)詳解

Nodejs 將消息循環(huán)又細(xì)分為 6 個(gè)階段(官方叫做 Phase), 每個(gè)階段都會(huì)有一個(gè)類似于隊(duì)列的結(jié)構(gòu), 存儲(chǔ)著該階段需要處理的回調(diào)函數(shù).

Nodejs 為了防止某個(gè) 階段 任務(wù)太多, 導(dǎo)致后續(xù)的 階段 發(fā)生饑餓的現(xiàn)象, 所以消息循環(huán)的每一個(gè)迭代(iterate) 中, 每個(gè) 階段 執(zhí)行回調(diào)都有個(gè)最大數(shù)量. 如果超過數(shù)量的話也會(huì)強(qiáng)行結(jié)束當(dāng)前 階段而進(jìn)入下一個(gè) 階段. 這一條規(guī)則適用于消息循環(huán)中的每一個(gè) 階段.

3.1 Timer 階段

這是消息循環(huán)的第一個(gè)階段, 用一個(gè) for 循環(huán)處理所有 setTimeoutsetInterval 的回調(diào).

這些回調(diào)被保存在一個(gè)最小堆(min heap) 中. 這樣引擎只需要每次判斷頭元素, 如果符合條件就拿出來執(zhí)行, 直到遇到一個(gè)不符合條件或者隊(duì)列空了, 才結(jié)束 Timer Phase.

Timer 階段中判斷某個(gè)回調(diào)是否符合條件的方法也很簡(jiǎn)單. 消息循環(huán)每次進(jìn)入 Timer 的時(shí)候都會(huì)保存一下當(dāng)時(shí)的系統(tǒng)時(shí)間,然后只要看上述最小堆中的回調(diào)函數(shù)設(shè)置的啟動(dòng)時(shí)間是否超過進(jìn)入 Timer 時(shí)保存的時(shí)間, 如果超過就拿出來執(zhí)行.

3.2 Pending I/O Callback 階段

執(zhí)行除了close callbackssetTimeout()、setInterval()、setImmediate()回調(diào)之外幾乎所有回調(diào),比如說TCP連接發(fā)生錯(cuò)誤fs.read, socket 等 IO 操作的回調(diào)函數(shù), 同時(shí)也包括各種 error 的回調(diào).

3.3 Idle, Prepare 階段

系統(tǒng)內(nèi)部的一些調(diào)用。

3.4 Poll 階段,重要階段

這是整個(gè)消息循環(huán)中最重要的一個(gè) 階段, 作用是等待異步請(qǐng)求和數(shù)據(jù),因?yàn)樗瘟苏麄€(gè)消息循環(huán)機(jī)制.

poll階段有兩個(gè)主要的功能:一是執(zhí)行下限時(shí)間已經(jīng)達(dá)到的timers的回調(diào),一是處理poll隊(duì)列里的事件。
注:Node的很多API都是基于事件訂閱完成的,比如fs.readFile,這些回調(diào)應(yīng)該都在poll階段完成。

當(dāng)事件循環(huán)進(jìn)入poll階段:

poll隊(duì)列不為空的時(shí)候,事件循環(huán)肯定是先遍歷隊(duì)列并同步執(zhí)行回調(diào),直到隊(duì)列清空或執(zhí)行回調(diào)數(shù)達(dá)到系統(tǒng)上限。

poll隊(duì)列為空的時(shí)候,這里有兩種情況。

如果代碼已經(jīng)被setImmediate()設(shè)定了回調(diào),那么事件循環(huán)直接結(jié)束poll階段進(jìn)入check階段來執(zhí)行check隊(duì)列里的回調(diào)。

如果代碼沒有被設(shè)定setImmediate()設(shè)定回調(diào):

如果有被設(shè)定的timers,那么此時(shí)事件循環(huán)會(huì)檢查timers,如果有一個(gè)或多個(gè)timers下限時(shí)間已經(jīng)到達(dá),那么事件循環(huán)將繞回timers階段,并執(zhí)行timers的有效回調(diào)隊(duì)列。

如果沒有被設(shè)定timers,這個(gè)時(shí)候事件循環(huán)是阻塞在poll階段等待事件回調(diào)被加入poll隊(duì)列。

Poll階段,當(dāng)js層代碼注冊(cè)的事件回調(diào)都沒有返回的時(shí)候,事件循環(huán)會(huì)暫時(shí)阻塞在poll階段,解除阻塞的條件:


在poll階段執(zhí)行的時(shí)候,會(huì)傳入一個(gè)timeout超時(shí)時(shí)間,該超時(shí)時(shí)間就是poll階段的最大阻塞時(shí)間。

timeout時(shí)間未到的時(shí)候,如果有事件返回,就執(zhí)行該事件注冊(cè)的回調(diào)函數(shù)。timeout超時(shí)時(shí)間到了,則退出poll階段,執(zhí)行下一個(gè)階段。

這個(gè) timeout 設(shè)置為多少合適呢? 答案就是 Timer Phase 中最近要執(zhí)行的回調(diào)啟動(dòng)時(shí)間到現(xiàn)在的差值, 假設(shè)這個(gè)差值是 detal. 因?yàn)?Poll Phase 后面沒有等待執(zhí)行的回調(diào)了. 所以這里最多等待 delta 時(shí)長(zhǎng), 如果期間有事件喚醒了消息循環(huán), 那么就繼續(xù)下一個(gè) Phase 的工作; 如果期間什么都沒發(fā)生, 那么到了 timeout 后, 消息循環(huán)依然要進(jìn)入后面的 Phase, 讓下一個(gè)迭代的 Timer Phase 也能夠得到執(zhí)行.
Nodejs 就是通過 Poll Phase, 對(duì) IO 事件的等待和內(nèi)核異步事件的到達(dá)來驅(qū)動(dòng)整個(gè)消息循環(huán)的.

3.5 Check 階段

這個(gè)階段只處理 setImmediate 的回調(diào)函數(shù).
那么為什么這里要有專門一個(gè)處理 setImmediate 的 階段 呢? 簡(jiǎn)單來說, 是因?yàn)?Poll 階段可能設(shè)置一些回調(diào), 希望在 Poll 階段 后運(yùn)行. 所以在 Poll 階段 后面增加了這個(gè) Check 階段.

3.6 Close Callbacks 階段

專門處理一些 close 類型的回調(diào). 比如 socket.on("close", ...). 用于資源清理.

4. nodejs執(zhí)行JS代碼過程及事件循環(huán)過程

1、node初始化

初始化node環(huán)境

執(zhí)行輸入的代碼

執(zhí)行process.nextTick回調(diào)

執(zhí)行微任務(wù)(microtasks)

2、進(jìn)入事件循環(huán)

2.1、進(jìn)入Timer階段

檢查Timer隊(duì)列是否有到期的Timer的回調(diào),如果有,將到期的所有Timer回調(diào)按照TimerId升序執(zhí)行

檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行

檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行

退出該階段

2.2、進(jìn)入Pending I/O Callback階段

檢查是否有Pending I/O Callback的回調(diào),如果有,執(zhí)行回調(diào)。如果沒有退出該階段

檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行

檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行

退出該階段

2.3、進(jìn)入idle,prepare階段

這個(gè)階段與JavaScript關(guān)系不大,略過

2.4、進(jìn)入Poll階段

首先檢查是否存在尚未完成的回調(diào),如果存在,分如下兩種情況:

第一種情況:有可執(zhí)行的回調(diào)

執(zhí)行所有可用回調(diào)(包含到期的定時(shí)器還有一些IO事件等)

檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行

檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行

退出該階段

第二種情況:沒有可執(zhí)行的回調(diào)

檢查是否有immediate回調(diào),如果有,退出Poll階段。如果沒有,阻塞在此階段,等待新的事件通知

如果不存在尚未完成的回調(diào),退出Poll階段

2.5、進(jìn)入check階段

如果有immediate回調(diào),則執(zhí)行所有immediate回調(diào)

檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行

檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行

退出該階段

2.6、進(jìn)入closing階段

如果有immediate回調(diào),則執(zhí)行所有immediate回調(diào)

檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行

檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行

退出該階段

3、檢查是否有活躍的handles(定時(shí)器、IO等事件句柄)

如果有,繼續(xù)下一輪事件循環(huán)

如果沒有,結(jié)束事件循環(huán),退出程序

注意:

事件循環(huán)的每一個(gè)子階段退出之前都會(huì)按順序執(zhí)行如下過程:

檢查是否有 process.nextTick 回調(diào),如果有,全部執(zhí)行。

檢查是否有 微任務(wù)(promise),如果有,全部執(zhí)行。

4.1 關(guān)于Promise和process.nextTick

事件循環(huán)隊(duì)列先保證所有的process.nextTick回調(diào),然后將所有的Promise回調(diào)追加在后面,最終在每個(gè)階段結(jié)束的時(shí)候一次性拿出來執(zhí)行。

此外,process.nextTickPromise回調(diào)的數(shù)量是受限制的,也就是說,如果一直往這個(gè)隊(duì)列中加入回調(diào),那么整個(gè)事件循環(huán)就會(huì)被卡住。

4.2 關(guān)于setTimeout(…, 0) 和 setImmediate

這兩個(gè)方法的回調(diào)到底誰快?

如下面的例子:

setImmediate(() => console.log(2))
setTimeout(() => console.log(1))

使用nodejs多次執(zhí)行后,發(fā)現(xiàn)輸出結(jié)果有時(shí)是1 2,有時(shí)是2 1

對(duì)于多次執(zhí)行輸出結(jié)果不同,需要了解事件循環(huán)的基礎(chǔ)問題。

首先,Nodejs啟動(dòng),初始化環(huán)境后加載我們的JS代碼(index.js).發(fā)生了兩件事(此時(shí)尚未進(jìn)入消息循環(huán)環(huán)節(jié)):

setImmediate 向 Check 階段 中添加了回調(diào) console.log(2); 

setTimeout 向 Timer 階段 中添加了回調(diào) console.log(1)

這時(shí)候, 要初始化階段完畢, 要進(jìn)入 Nodejs 消息循環(huán)了。

為什么會(huì)有兩種輸出呢? 接下來一步很關(guān)鍵:

當(dāng)執(zhí)行到 Timer 階段 時(shí), 會(huì)發(fā)生兩種可能. 因?yàn)槊恳惠喌鷦倓傔M(jìn)入 Timer 階段 時(shí)會(huì)取系統(tǒng)時(shí)間保存起來, 以 ms(毫秒) 為最小單位.

如果 Timer 階段 中回調(diào)預(yù)設(shè)的時(shí)間 > 消息循環(huán)所保存的時(shí)間, 則執(zhí)行 Timer 階段 中的該回調(diào). 這種情況下先輸出 1, 直到 Check 階段 執(zhí)行后,輸出2.總的來說, 結(jié)果是 1 2.

如果運(yùn)行比較快, Timer 階段 中回調(diào)預(yù)設(shè)的時(shí)間可能剛好等于消息循環(huán)所保存的時(shí)間, 這種情況下, Timer 階段 中的回調(diào)得不到執(zhí)行, 則繼續(xù)下一個(gè) 階段. 直到 Check 階段, 輸出 2. 然后等下一輪迭代的 Timer 階段, 這時(shí)的時(shí)間一定是滿足 Timer 階段 中回調(diào)預(yù)設(shè)的時(shí)間 > 消息循環(huán)所保存的時(shí)間 , 所以 console.log(1) 得到執(zhí)行, 輸出 1. 總的來說, 結(jié)果就是 2 1.

所以, 輸出不穩(wěn)定的原因就取決于進(jìn)入 Timer 階段 的時(shí)間是否和執(zhí)行 setTimeout 的時(shí)間在 1ms 內(nèi). 如果把代碼改成如下, 則一定會(huì)得到穩(wěn)定的輸出:

require("fs").readFile("my-file-path.txt", () => {
 setImmediate(() => console.log(2))
 setTimeout(() => console.log(1))
});

這是因?yàn)橄⒀h(huán)在 Pneding I/O Phase 才向 Timer 和 Check 隊(duì)列插入回調(diào). 這時(shí)按照消息循環(huán)的執(zhí)行順序, Check 一定在 Timer 之前執(zhí)行。

從性能角度講, setTimeout 的處理是在 Timer Phase, 其中 min heap 保存了 timer 的回調(diào), 因此每執(zhí)行一個(gè)回調(diào)的同時(shí)都會(huì)涉及到堆調(diào)整. 而 setImmediate 僅僅是清空一個(gè)隊(duì)列. 效率自然會(huì)高很多.

再從執(zhí)行時(shí)機(jī)上講. setTimeout(..., 0) 和 setImmediate 完全屬于兩個(gè)階段.

5. 一個(gè)實(shí)際例子演示

下面以一段代碼來說明nodejs運(yùn)行JavaScript的機(jī)制。

如下面一段代碼:

setTimeout(() => {                                                // settimeout1
  console.log("1")
  new Promise((resolve) => { console.log("2"); resolve(); })      // Promise3
  .then(() => { console.log("3") })
  new Promise((resolve)=> { console.log("4"); resolve()})         // Promise4
  .then(() => { console.log("5") })
  setTimeout(() => {                                              // settimeout3
    console.log("6")
    setTimeout(() => {                                            // settimeout5
      console.log("7")
      new Promise((resolve) => { console.log("8"); resolve() })   // Promise5
      .then( () => {  console.log("9") })
      new Promise((resolve) => { console.log("10"); resolve() })  // Promise6
      .then(() => {  console.log("11") })
    })
    setTimeout(() => { console.log("12") }, 0)                    // settimeout6
  })
  setTimeout(() => { console.log("13") }, 0)                      // settimeout4
})
setTimeout(() => { console.log("14") }, 0)                        // settimeout2
new Promise((resolve) => { console.log("15"); resolve() })        // Promise1
.then( ()=> { console.log("16") })
new Promise((resolve) => { console.log("17"); resolve() })        // Promise2
.then(() => { console.log("18") })

上面代碼執(zhí)行過程:

node初始化

執(zhí)行JavaScript代碼

遇到setTimeout, 把回調(diào)函數(shù)放到Timer隊(duì)列中,記為settimeout1

遇到setTimeout, 把回調(diào)函數(shù)放到Timer隊(duì)列中,記為settimeout2

遇到Promise,執(zhí)行,輸出15,把回調(diào)函數(shù)放到微任務(wù)隊(duì)列,記為Promise1

遇到Promise,執(zhí)行,輸出17,把回調(diào)函數(shù)放到微任務(wù)隊(duì)列,記為Promise2

代碼執(zhí)行結(jié)束,此階段輸出結(jié)果:15 17

沒有process.nextTick回調(diào),略過

執(zhí)行微任務(wù)

檢查微任務(wù)隊(duì)列是否有可執(zhí)行回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):Promise1、Promise2

執(zhí)行Promise1回調(diào),輸出16

執(zhí)行Promise2回調(diào),輸出18

此階段輸出結(jié)果:16 18

進(jìn)入第一次事件循環(huán)

進(jìn)入Timer階段

檢查Timer隊(duì)列是否有可執(zhí)行的回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):settimeout1、settimeout2

執(zhí)行settimeout1回調(diào):

輸出1、2、4

添加了2個(gè)微任務(wù),記為Promise3、Promise4

添加了2個(gè)Timer任務(wù),記為settimeout3、settimeout4

執(zhí)行settimeout2回調(diào),輸出14

Timer隊(duì)列任務(wù)執(zhí)行完畢

沒有process.nextTick回調(diào),略過

檢查微任務(wù)隊(duì)列是否有可執(zhí)行回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):Promise3、Promise4

按順序執(zhí)行2個(gè)微任務(wù),輸出3、5

此階段輸出結(jié)果:1 2 4 14 3 5

Pending I/O Callback階段沒有任務(wù),略過

進(jìn)入 Poll 階段

檢查是否存在尚未完成的回調(diào),此時(shí)有2個(gè)回調(diào):settimeout3、settimeout4

執(zhí)行settimeout3回調(diào)

輸出6

添加了2個(gè)Timer任務(wù),記為settimeout5、settimeout6

執(zhí)行settimeout4回調(diào),輸出13

沒有process.nextTick回調(diào),略過

沒有微任務(wù),略過

此階段輸出結(jié)果:6 13

check、closing階段沒有任務(wù),略過

檢查是否還有活躍的handles(定時(shí)器、IO等事件句柄),有,繼續(xù)下一輪事件循環(huán)

進(jìn)入第二次事件循環(huán)

進(jìn)入Timer階段

檢查Timer隊(duì)列是否有可執(zhí)行的回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):settimeout5、settimeout6

執(zhí)行settimeout5回調(diào):

輸出7、 8、10

添加了2個(gè)微任務(wù),記為Promise5、Promise6

執(zhí)行settimeout6回調(diào),輸出12

沒有process.nextTick回調(diào),略過

檢查微任務(wù)隊(duì)列是否有可執(zhí)行回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):Promise5、Promise6

按順序執(zhí)行2個(gè)微任務(wù),輸出9、11

此階段輸出結(jié)果:7 8 10 12 9 11

Pending I/O Callback、Poll、check、closing階段沒有任務(wù),略過

檢查是否還有活躍的handles(定時(shí)器、IO等事件句柄),沒有了,結(jié)束事件循環(huán),退出程序

程序執(zhí)行結(jié)束,輸出結(jié)果:15 17 16 18 1 2 4 14 3 5 6 13 7 8 10 12 9 11

參考資料

深入分析Node.js事件循環(huán)與消息隊(duì)列

剖析nodejs的事件循環(huán)

Node中的事件循環(huán)和異步API

Node.js Event Loop nodejs官網(wǎng)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/109305.html

相關(guān)文章

  • JS與Node.js中的事件循環(huán)

    摘要:的單線程,與它的用途有關(guān)。特點(diǎn)的顯著特點(diǎn)異步機(jī)制事件驅(qū)動(dòng)。隊(duì)列的讀取輪詢線程,事件的消費(fèi)者,的主角。它將不同的任務(wù)分配給不同的線程,形成一個(gè)事件循環(huán),以異步的方式將任務(wù)的執(zhí)行結(jié)果返回給引擎。 這兩天跟同事同事討論遇到的一個(gè)問題,js中的event loop,引出了chrome與node中運(yùn)行具有setTimeout和Promise的程序時(shí)候執(zhí)行結(jié)果不一樣的問題,從而引出了Nodejs的...

    abson 評(píng)論0 收藏0
  • JavaScript運(yùn)行機(jī)制事件循環(huán)

    摘要:主線程不斷重復(fù)上面的三步,此過程也就是常說的事件循環(huán)。所以主線程代碼執(zhí)行時(shí)間過長(zhǎng),會(huì)阻塞事件循環(huán)的執(zhí)行。參考資料這一次,徹底弄懂執(zhí)行機(jī)制任務(wù)隊(duì)列的順序機(jī)制事件循環(huán)搞懂異步事件輪詢與中的事件循環(huán) 1. 說明 讀過本文章后,您能知道: JavaScript代碼在瀏覽器中的執(zhí)行機(jī)制和事件循環(huán) 面試中經(jīng)常遇到的代碼輸出順序問題 首先通過一段代碼來驗(yàn)證你是否了解代碼輸出順序,如果你不知道輸出...

    Ververica 評(píng)論0 收藏0
  • Nodejs高性能原理(上) --- 異步非阻塞事件驅(qū)動(dòng)模型

    摘要:使用了一個(gè)事件驅(qū)動(dòng)非阻塞式的模型,使其輕量又高效。的包管理器,是全球最大的開源庫生態(tài)系統(tǒng)。按照這個(gè)定義,之前所述的阻塞,非阻塞,多路復(fù)用信號(hào)驅(qū)動(dòng)都屬于同步。 系列文章 Nodejs高性能原理(上) --- 異步非阻塞事件驅(qū)動(dòng)模型Nodejs高性能原理(下) --- 事件循環(huán)詳解 前言 終于開始我nodejs的博客生涯了,先從基本的原理講起.以前寫過一篇瀏覽器執(zhí)行機(jī)制的文章,和nodej...

    yy736044583 評(píng)論0 收藏0
  • 瀏覽器與NodeJS的EventLoop異同,以及部分機(jī)制

    摘要:瀏覽器與的異同,以及部分機(jī)制有人對(duì)部分迷惑,本身構(gòu)造函數(shù)是同步的,是異步。瀏覽器的的已全部分析完成,過程中引用阮一峰博客,知乎,部分文章內(nèi)容,侵刪。 瀏覽器與NodeJS的EventLoop異同,以及部分機(jī)制 PS:有人對(duì)promise部分迷惑,Promise本身構(gòu)造函數(shù)是同步的,.then是異步。---- 2018/7/6 22:35修改 javascript 是一門單線程的腳本...

    jubincn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<