成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

關于 Promise 的執行順序

開發 前端
我們知道,Promise 實例化時,傳入的回調會立即執行,而Promise 的 then 回調會被放到微任務隊列中,等待執行。

最近看到一個 Promise 相關的很有意思的代碼:

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

第一次看到這個代碼的時候,以為的輸出結果會是:1,2,3,4,但是被實際的輸出結果打臉 。

如圖所示,實際的輸出結果為:1,2,4,3。

代碼分析

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

我們知道,Promise 實例化時,傳入的回調會立即執行,而Promise 的 then 回調會被放到微任務隊列中,等待執行。隊列就是一個先進先出的列表,先被放到隊列的回調,會被優先執行。前面的代碼中,一共有 5 個回調函數。

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

Promise 實例化完成后,第一個 then() 方法被調用, 回調2 會被放入了微任務隊列中,等待執行。

then 方法何時調用?

這個時候疑問點來了,第一個 then() 方法被調用后,第二個 then 方法會不會馬上被調用,如果會,那輸出的結果就應該是 :1,2,3,4。顯然,此時不會馬上調用第二個 then() 方法,也就是不會馬上將 回調5 放入微任務隊列。那如果不會,那何時才會被調用?

這個時候,需要看一下 Promise/A+ 規范。重點是下面幾條:

2.2 then 方法promise 的 then 方法接受兩個參數:

promise.then(onFulfilled, onRejected)

2.2.2 如果 onFulfilled 是函數:

  • 2.2.2.1 當 promise 處于已處理狀態時,該函數必須被調用并將 promise 的值作為第一個參數。
  • 2.2.2.2 該函數一定不能在 promise 處于已處理狀態之前調用。
  • 2.2.2.3 該函數被調用次數不超過一次。

2.2.6 then 可以在同一個 promise 上多次調用。

  • 2.2.6.1 如果 promise 處于已處理狀態時,所有相應的 onFulfilled 回調必須按照它們對 then 的組織順序依次調用。
  • 2.2.6.2 如果 promise 處于已拒絕狀態時,所有相應的 onRejected 回調必須按照它們對 then 的組織順序依次調用。

2.2.7 then 必須返回一個 promise。

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

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

綜上,第一個 then() 方法調用后,會返回一個新的 Promise。這樣做的目的就是為了保持鏈式調用,而且 then() 方法內的 onFulfilled 回調會等待 Promise 狀態修改之后才會調用。

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

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() 會返回一個新的 Promise 命名為 p2,后面的 p2.then() 的回調會在 p1.then() 內的回調函數執行完之后,才會調用,也就是 p2 這個 Promise 狀態發生改變之后。

所以,只有 回調2 執行完成后,才會執行 p2.then()。我們再看 回調2 的內容。

回調2 先是對一個 Promise 進行了實例化操作,實例化的回調為 回調3 ,該回調會立即執行,此時控制臺打印出數字 2,然后 resolve() 方法被調用,此時的 Promise 狀態被修改成了 fulfilled,后面的 回調4 會放入微任務隊列。回調2 執行完畢后,執行 p2.then(),回調5 被放入微任務隊列。

按照隊列先進先出的執行順序,先執行 回調4,然后執行 回調5。所以,在控制臺會先輸出數字 4,然后輸出數字 3。

如果想要輸出的結果為: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)
})

根據前面的 2.2.6 規則,then 可以在同一個 promise 上多次調用,且 p1 后面的 then 會按照他們的調用順序直接放入微任務隊列中。

責任編輯:姜華 來源: 自然醒的筆記本
相關推薦

2018-03-13 16:04:45

Promise執行順序

2024-10-11 17:13:14

SQL數據庫查詢數據庫

2012-05-16 13:45:24

Java構造器

2025-02-07 15:01:49

Promise數組前端

2024-03-06 13:56:00

項目awaitpromise

2024-01-02 16:16:34

Promise前端

2010-04-16 09:27:18

Ocacle執行計劃

2021-07-28 07:22:40

SQL順序Hive

2019-11-06 09:30:35

SQL查詢語句數據庫

2009-07-03 16:33:13

Tapestry函數執

2022-10-11 23:50:43

JavaScript編程Promise

2010-09-03 14:47:50

SQLSELECT語句

2009-11-10 16:00:05

Oracle執行計劃

2020-07-29 17:35:08

Promise源碼前端

2021-09-26 09:59:14

MYSQL開發數據庫

2022-05-10 08:47:00

JMeter作用域執行順序

2010-08-27 13:07:00

CSS規則

2023-09-15 15:31:23

異步編程Promise

2022-09-02 08:19:37

spring配置加載

2022-02-16 13:46:40

Spring Aop代碼注解
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜视频免费网站 | 精品国产乱码久久久久久蜜退臀 | 米奇7777狠狠狠狠视频 | 国产精品久久一区 | 国产精品国产精品国产专区不片 | 亚洲国产18 | 日本一区二区高清不卡 | 欧美成视频 | 欧美天堂| 天天看天天摸天天操 | 国产精品久久精品 | 国产中文视频 | 国产免费一区二区三区免费视频 | 久久精品91 | 欧美最猛黑人xxxⅹ 粉嫩一区二区三区四区公司1 | 可以在线看的黄色网址 | 国产成人免费一区二区60岁 | 国产精品精品视频一区二区三区 | 天天搞夜夜操 | xx视频在线 | 欧美精三区欧美精三区 | 国产一区二区在线播放 | 欧美日韩a | 在线免费黄色 | 在线一区二区三区 | 欧美激情区| 国产在线观看一区 | 精品国产乱码久久久久久a丨 | 国产一级在线 | 午夜在线观看视频 | 日韩欧美在 | 国产综合精品 | av网站在线看 | 国产日韩一区 | 毛片大全 | 精品国产91久久久久久 | 国产欧美二区 | av网站在线播放 | 欧美成人h版在线观看 | 天天综合久久网 | 亚州春色|