欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript中Promise的執(zhí)行順序詳解

 更新時間:2022年01月26日 10:30:50   作者:自然醒  
Promise 是 JS 中進行異步編程的新的解決方案(舊的是純回調(diào)形式) ,下面這篇文章主要給大家介紹了關(guān)于JavaScript中Promise執(zhí)行順序的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

最近看到一個 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)
})

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

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

代碼分析

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

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

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

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

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

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

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

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

promise.then(onFulfilled, onRejected)

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

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

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

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

2.2.7 then 必須返回一個 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 個 onFulfilled,按照 1、2、3 的順序執(zhí)行
// 調(diào)用 .then 方法后,返回一個新的 promise
promise2 = promise1.then(onFulfilled, onRejected);

綜上,第一個 then() 方法調(diào)用后,會返回一個新的 Promise。這樣做的目的就是為了保持鏈?zhǔn)秸{(diào)用,而且 then() 方法內(nèi)的 onFulfilled 回調(diào)會等待 Promise 狀態(tài)修改之后才會調(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() 會返回一個新的 Promise 命名為 p2,后面的 p2.then() 的回調(diào)會在 p1.then() 內(nèi)的回調(diào)函數(shù)執(zhí)行完之后,才會調(diào)用,也就是 p2 這個 Promise 狀態(tài)發(fā)生改變之后。

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

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

按照隊列先進先出的執(zhí)行順序,先執(zhí)行 回調(diào)4,然后執(zhí)行 回調(diào)5。所以,在控制臺會先輸出數(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 可以在同一個 promise 上多次調(diào)用,且 p1 后面的 then 會按照他們的調(diào)用順序直接放入微任務(wù)隊列中。

總結(jié)

到此這篇關(guān)于JavaScript中Promise執(zhí)行順序的文章就介紹到這了,更多相關(guān)js Promise的執(zhí)行順序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • uniapp實現(xiàn)下拉刷新的幾種方式小結(jié)

    uniapp實現(xiàn)下拉刷新的幾種方式小結(jié)

    原生的uniapp的下拉刷新是一個普通的加載框,樣式真的很單一,下面這篇文章主要總結(jié)介紹了uniapp實現(xiàn)下拉刷新的幾種方式,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • uniapp中uni.switchTab無法傳參的解決辦法

    uniapp中uni.switchTab無法傳參的解決辦法

    uni.switchTab跳轉(zhuǎn)的必須是TabBar上的路徑,下面這篇文章主要給大家介紹了關(guān)于uniapp中uni.switchTab無法傳參的解決辦法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • Bootstrap編寫導(dǎo)航欄和登陸框

    Bootstrap編寫導(dǎo)航欄和登陸框

    這篇文章主要為大家詳細(xì)介紹了Bootstrap導(dǎo)航欄和登陸框的編寫代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • 一篇文章讓你搞懂JavaScript 原型和原型鏈

    一篇文章讓你搞懂JavaScript 原型和原型鏈

    這篇文章主要介紹了一篇文章讓你搞懂JavaScript 原型和原型鏈,幫助大家更好的理解和學(xué)習(xí)JavaScript,感興趣的朋友可以了解下
    2020-11-11
  • Promise中的then鏈機制用法詳解

    Promise中的then鏈機制用法詳解

    這篇文章給大家詳細(xì)介紹了Promise中的then鏈機制用法,每一次 .then都會返回一個新的promise實例,文中通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • 微信小程序?qū)崿F(xiàn)圖片上傳

    微信小程序?qū)崿F(xiàn)圖片上傳

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)圖片上傳,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • HTML+JS實現(xiàn)3D倒計時爆炸特效

    HTML+JS實現(xiàn)3D倒計時爆炸特效

    這篇文章主要為大家詳細(xì)介紹了如何結(jié)合HTML與JS實現(xiàn)3D倒計時爆炸特效,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,有需要的小伙伴可以參考下
    2024-01-01
  • 第一次接觸神奇的Bootstrap基礎(chǔ)排版

    第一次接觸神奇的Bootstrap基礎(chǔ)排版

    第一次接觸神奇的Bootstrap基礎(chǔ)排版,Bootstrap讓W(xué)eb開發(fā)更迅速、更簡單,感興趣的小伙伴們可以參考一下
    2016-07-07
  • JavaScript prototype對象的屬性說明

    JavaScript prototype對象的屬性說明

    JavaScript中對象的prototype屬性,是用來返回對象類型原型的引用的。我們使用prototype屬性提供對象的類的一組基本功能。并且對象的新實例會”繼承”賦予該對象原型的操作。但是這個prototype到底是怎么實現(xiàn)和被管理的呢?
    2010-03-03
  • JavaScript使用箭頭函數(shù)實現(xiàn)優(yōu)化代碼

    JavaScript使用箭頭函數(shù)實現(xiàn)優(yōu)化代碼

    在JavaScript的編程世界里,我們時常被普通函數(shù)的冗長寫法所困擾,每次都需要寫function關(guān)鍵字,有時候還要明確地寫return語句,下面我們就來看看如何利用箭頭函數(shù)優(yōu)化這些繁瑣的代碼吧
    2023-11-11

最新評論