[英]How to understand this Promise execution order?
我不明白為什么這段代碼會導致這樣的順序? 誰能詳細說明一下? 我認為 Promises 就像一個 FIFO 隊列,但是嵌套的 Promise 函數似乎有點不可預測,或者可能使用其他一些數據結構?
new Promise(resolve => { resolve() }).then(() => { new Promise(resolve => { resolve() }).then(() => { console.log(1) }).then(() => { console.log(2) }).then(() => { console.log(3.1) }) }).then(() => { console.log(1.1) new Promise((resolve => { resolve() })).then(() => { new Promise(resolve => { resolve() }).then(() => { console.log(4) }).then(() => { console.log(6) }) }).then(() => { console.log(5) }) }).then(() => { console.log(3) }) console.log(0)
Output:
0
1
1.1
2
3
3.1
4
5
6
承諾是異步的。 這意味着每次你創建一個新的 Promise 時,都會啟動一個新的異步操作。
什么是 JS 中的異步操作? 首先你需要明白,無論你做什么,JS 都是在單線程上運行的。 所以,為了讓它看起來像它的異步 - 有一個叫做“事件循環”的東西(從評論到原始帖子的鏈接,tnx @Taki 的偉大來源)。
一般來說,事件循環存儲所有異步函數和主代碼動作之間的動作中的“滑動”。 這確實是過於簡化的解釋,請參閱鏈接以了解更多信息,但這就是它的要點。
所以基本上,這里沒有“FIFO”隊列——異步函數的順序實際上取決於你的處理器速度、操作系統等。
但是-有一種方法可以確保一個異步操作僅在另一個異步操作完成后才執行,這就是.then
子句。 問題是,它只保證 .then 中的特定.then
將在它連接到的特定 promise 之后執行,但它沒有說明它與事件循環中其他異步操作(承諾)的順序有關. 因此,例如在您的代碼中:
new Promise(resolve => {
resolve() // PROMISE A
})
.then(() => {
new Promise(resolve => {
resolve() // PROMISE B
})
.then(() => {
console.log(1) //PROMISE C
})
.then(() => {
console.log(2)
})
.then(() => {
console.log(3.1)
})
})
.then(() => {
console.log(1.1) // PROMISE D
new Promise((resolve => {
resolve()
}))
我采取了其中的一部分來解釋:
因此,Promise A 首先解析。 這確保了 promise B 現在將解決。 這是事情變得復雜的時候:由於 promise B 已解決,promise C 和 D 現在都進入事件循環了嗎? 為什么? because Promise A had 2 .then
clauses, so when the first one ends- event loop takes the 2nd one which is promise D. but the first .then
clause had also a .then
clause of his own - promise C, which also enters the事件循環。
PROMISE D 和 C 之間沒有連接。 它們可以按任何順序執行,保持這種邏輯,您將看到它如何適用於 Promise 的 rest。 而且,如果您嘗試在不同的操作系統上運行它,則由於事件循環的操作系統實現不同,因此承諾順序可能會有所不同。
希望這可以幫助您了解一點。
免責聲明:我在 JS 方面沒有太多經驗,但 promise 確實讓我很感興趣,所以我對它進行了深入研究。 我支持我在這里寫的所有內容,但如果對我的解釋有任何更正,我很想聽聽!
編輯
我下面的答案也是正確的,但沒有任何解釋,所以讓我補充一下:當您不返回 promise (或也返回承諾的.then
子句)內的任何內容時,它將隱式返回已解析的 promise no value before going out of the promise, basically like adding a return new Promise.resolve()
after teh console.log
in promise C, for example. 當它像這樣完成時,promise B 之后的所有.then
子句只會在前一個結束后進入事件循環(例如 b 結束,所以 C 進入循環,然后是下一個.then
等等),但在它們之間其他承諾或.then
子句(如 promise D)也可以輸入。
但是,當您返回帶有.then
子句的 promise 時,它會確保 promise + then 子句的整個塊按順序進入事件循環,因此.then
子句也將按順序執行你自找的:)
tnx @Eugene Sunic 補充!
由於代碼中不存在的返回,它會導致不可預測的順序。
將回報添加到您的 Promise 中,您將獲得可理解的輸出,並且可以輕松跟蹤 Promise 的執行情況。
首先,打印同步 0,然后執行整個第一個 promise 塊,就像你說的 FIFO。
1,2, 3.1
之后鏈接 thenable 被執行 1.1 之后塊 4,6 被打印
在輸出 5 的鏈接 thenable 之后,最后一個 thenable 打印數字 3
給我們留下 0,1,2,3.1,1.1,4,6,5,3
new Promise(resolve => resolve()).then(() => { return new Promise(resolve => resolve()).then(() => console.log(1)).then(() => console.log(2)).then(() => console.log(3.1)); }).then(() => { console.log(1.1); return new Promise((resolve => resolve())).then(() => { return new Promise((resolve) => resolve()).then(() => console.log(4)).then(() => console.log(6)) }).then(() => console.log(5)) }).then(() => console.log(3)) console.log(0)
它是 FIFO,執行如下所示:
main [4] logs: 0 // main code executed, one executor added to FIFO (4)
4 [8,18] // executor at line 4 runs, two executors added to FIFO (8, 18)
8 [18,11] logs: 1 // etc etc
18 [11,23,36] logs: 1.1
11 [23,36,14] logs: 2
23 [36,14,27,33]
36 [14,27,33] logs: 3
14 [27,33] logs: 3.1
27 [33,30] logs: 4
33 [30] logs: 5
30 logs: 6
正如您所看到的,它的先進先出順序: [4,8,18,11,23,36,14,27,33,30]
但它存儲執行程序(已實現或拒絕的承諾的回調),而不是承諾。 換句話說:promise 完成或拒絕的時間決定了它何時添加到 FIFO,而不是 promise 的創建時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.