自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

關(guān)于 Promise 的執(zhí)行順序

開發(fā) 前端
我們知道,Promise 實(shí)例化時(shí),傳入的回調(diào)會(huì)立即執(zhí)行,而Promise 的 then 回調(diào)會(huì)被放到微任務(wù)隊(duì)列中,等待執(zhí)行。

最近看到一個(gè) Promise 相關(guān)的很有意思的代碼:

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

第一次看到這個(gè)代碼的時(shí)候,以為的輸出結(jié)果會(huì)是:1,2,3,4,但是被實(shí)際的輸出結(jié)果打臉 。

如圖所示,實(shí)際的輸出結(jié)果為:1,2,4,3。

代碼分析

為了搞清楚實(shí)際的輸出結(jié)果為什么是:1,2,4,3,我們來一步步分析代碼的執(zhí)行。

我們知道,Promise 實(shí)例化時(shí),傳入的回調(diào)會(huì)立即執(zhí)行,而Promise 的 then 回調(diào)會(huì)被放到微任務(wù)隊(duì)列中,等待執(zhí)行。隊(duì)列就是一個(gè)先進(jìn)先出的列表,先被放到隊(duì)列的回調(diào),會(huì)被優(yōu)先執(zhí)行。前面的代碼中,一共有 5 個(gè)回調(diào)函數(shù)。

回調(diào)1 是 Promise 實(shí)例化時(shí)的回調(diào),所以會(huì)立即執(zhí)行,此時(shí)控制臺(tái)打印出數(shù)字 1,然后 resolve() 方法被調(diào)用,此時(shí)的 Promise 狀態(tài)被修改成了 fulfilled(如果沒有調(diào)用 resolve() 方法,Promise 的狀態(tài)為 pending)。

Promise 實(shí)例化完成后,第一個(gè) then() 方法被調(diào)用, 回調(diào)2 會(huì)被放入了微任務(wù)隊(duì)列中,等待執(zhí)行。

then 方法何時(shí)調(diào)用?

這個(gè)時(shí)候疑問點(diǎn)來了,第一個(gè) then() 方法被調(diào)用后,第二個(gè) then 方法會(huì)不會(huì)馬上被調(diào)用,如果會(huì),那輸出的結(jié)果就應(yīng)該是 :1,2,3,4。顯然,此時(shí)不會(huì)馬上調(diào)用第二個(gè) then() 方法,也就是不會(huì)馬上將 回調(diào)5 放入微任務(wù)隊(duì)列。那如果不會(huì),那何時(shí)才會(huì)被調(diào)用?

這個(gè)時(shí)候,需要看一下 Promise/A+ 規(guī)范。重點(diǎn)是下面幾條:

2.2 then 方法promise 的 then 方法接受兩個(gè)參數(shù):

promise.then(onFulfilled, onRejected)

2.2.2 如果 onFulfilled 是函數(shù):

  • 2.2.2.1 當(dāng) promise 處于已處理狀態(tài)時(shí),該函數(shù)必須被調(diào)用并將 promise 的值作為第一個(gè)參數(shù)。
  • 2.2.2.2 該函數(shù)一定不能在 promise 處于已處理狀態(tài)之前調(diào)用。
  • 2.2.2.3 該函數(shù)被調(diào)用次數(shù)不超過一次。

2.2.6 then 可以在同一個(gè) promise 上多次調(diào)用。

  • 2.2.6.1 如果 promise 處于已處理狀態(tài)時(shí),所有相應(yīng)的 onFulfilled 回調(diào)必須按照它們對(duì) then 的組織順序依次調(diào)用。
  • 2.2.6.2 如果 promise 處于已拒絕狀態(tài)時(shí),所有相應(yīng)的 onRejected 回調(diào)必須按照它們對(duì) then 的組織順序依次調(diào)用。

2.2.7 then 必須返回一個(gè) promise。

promise1 = new Promise(resolve => resolve())

// promise1 可以多次調(diào)用 then
// 且 onFulfilled 回調(diào)的執(zhí)行順序,按照 .then 的調(diào)用順序執(zhí)行
promise1.then(onFulfilled1) // 1
promise1.then(onFulfilled2) // 2
promise1.then(onFulfilled3) // 3
// 上面 3 個(gè) onFulfilled,按照 1、2、3 的順序執(zhí)行
// 調(diào)用 .then 方法后,返回一個(gè)新的 promisepromise2 = promise1.then(onFulfilled, 
onRejected);

綜上,第一個(gè) then() 方法調(diào)用后,會(huì)返回一個(gè)新的 Promise。這樣做的目的就是為了保持鏈?zhǔn)秸{(diào)用,而且 then() 方法內(nèi)的 onFulfilled 回調(diào)會(huì)等待 Promise 狀態(tài)修改之后才會(huì)調(diào)用。

我們稍微修改一下前面代碼的調(diào)用形式,如下:

const p1 = new Promise((resolve) => {
console.log(1)
resolve()
})

const p2 = p1.then(() => {
new Promise((resolve) => {
console.log(2)
resolve()
}).then(() => {
console.log(4)
})
})

const p3 = p2.then(() => {
console.log(3)
})

p1.then() 會(huì)返回一個(gè)新的 Promise 命名為 p2,后面的 p2.then() 的回調(diào)會(huì)在 p1.then() 內(nèi)的回調(diào)函數(shù)執(zhí)行完之后,才會(huì)調(diào)用,也就是 p2 這個(gè) Promise 狀態(tài)發(fā)生改變之后。

所以,只有 回調(diào)2 執(zhí)行完成后,才會(huì)執(zhí)行 p2.then()。我們?cè)倏?回調(diào)2 的內(nèi)容。

回調(diào)2 先是對(duì)一個(gè) Promise 進(jìn)行了實(shí)例化操作,實(shí)例化的回調(diào)為 回調(diào)3 ,該回調(diào)會(huì)立即執(zhí)行,此時(shí)控制臺(tái)打印出數(shù)字 2,然后 resolve() 方法被調(diào)用,此時(shí)的 Promise 狀態(tài)被修改成了 fulfilled,后面的 回調(diào)4 會(huì)放入微任務(wù)隊(duì)列?;卣{(diào)2 執(zhí)行完畢后,執(zhí)行 p2.then(),回調(diào)5 被放入微任務(wù)隊(duì)列。

按照隊(duì)列先進(jìn)先出的執(zhí)行順序,先執(zhí)行 回調(diào)4,然后執(zhí)行 回調(diào)5。所以,在控制臺(tái)會(huì)先輸出數(shù)字 4,然后輸出數(shù)字 3。

如果想要輸出的結(jié)果為:1,2,3,4,可以將代碼改成如下形式:

const p1 = new Promise((resolve) => {
console.log(1)
resolve()
})

p1.then(() => {
new Promise((resolve) => {
console.log(2)
resolve()
}).then(() => {
console.log(4)
})
})

p1.then(() => {
console.log(3)
})

根據(jù)前面的 2.2.6 規(guī)則,then 可以在同一個(gè) promise 上多次調(diào)用,且 p1 后面的 then 會(huì)按照他們的調(diào)用順序直接放入微任務(wù)隊(duì)列中。

責(zé)任編輯:姜華 來源: 自然醒的筆記本
相關(guān)推薦

2018-03-13 16:04:45

Promise執(zhí)行順序

2024-10-11 17:13:14

SQL數(shù)據(jù)庫查詢數(shù)據(jù)庫

2012-05-16 13:45:24

Java構(gòu)造器

2024-03-06 13:56:00

項(xiàng)目awaitpromise

2025-02-07 15:01:49

Promise數(shù)組前端

2024-01-02 16:16:34

Promise前端

2010-04-16 09:27:18

Ocacle執(zhí)行計(jì)劃

2021-07-28 07:22:40

SQL順序Hive

2019-11-06 09:30:35

SQL查詢語句數(shù)據(jù)庫

2009-07-03 16:33:13

Tapestry函數(shù)執(zhí)

2010-09-03 14:47:50

SQLSELECT語句

2009-11-10 16:00:05

Oracle執(zhí)行計(jì)劃

2021-09-26 09:59:14

MYSQL開發(fā)數(shù)據(jù)庫

2022-05-10 08:47:00

JMeter作用域執(zhí)行順序

2010-08-27 13:07:00

CSS規(guī)則

2022-10-11 23:50:43

JavaScript編程Promise

2020-07-29 17:35:08

Promise源碼前端

2023-09-15 15:31:23

異步編程Promise

2022-02-16 13:46:40

Spring Aop代碼注解

2020-10-16 09:40:18

順序Spring AOPHTTP
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)