[英]Using Promise inside loop
我想了解這段代碼是如何工作的。 有一段時間我一直在努力,但我想知道這里發生了什么。
for(let i=0 ; i< 3 ;i++){
new Promise((resolve,reject)=>{
console.log("i = "+i)
resolve(i)
})
.then(r=>{
console.log("promise 1 of "+r)
return new Promise((res,rej)=>res(r))
})
.then(r=>{
console.log("promise 2 of "+r)
return new Promise((res,rej)=>res(r))
})
}
console.log("finish")
輸出是
i = 0
i = 1
i = 2
finish
promise 1 of 0
promise 1 of 1
promise 1 of 2
promise 2 of 0
promise 2 of 1
promise 2 of 2
為什么在其他承諾執行之前顯示完成。
提前致謝
為什么在其他承諾執行之前顯示完成。
因為該代碼中沒有任何內容告訴console.log
在運行之前等待promises完成。 如果你想這樣做,將它們收集到一個數組中,然后使用:
Promise.all(theArray)
.then(() => {
console.log("finish");
});
......告訴它等待他們。
請記住, then
處理器是始終異步調用。 所以,你的代碼創建三支諾鏈,然后輸出console.log
底,然后獲取異步回調到then
處理程序-這樣的結果表明了之后。
旁注:問題中的代碼可以更簡單地寫成:
for(let i = 0; i < 3; i++) {
console.log("i = " + i);
Promise.resolve(i)
.then(r => {
console.log("promise 1 of " + r);
return r;
})
.then(r => {
console.log("promise 2 of " + r);
return r;
});
}
console.log("finish");
為什么:
console.log("i = " + i);
之間沒有區別console.log("i = " + i);
line作為執行函數的第一行,或者在您創建promise的行的上方。 Promise.resolve
使用您提供的值創建已解決的承諾。 then
總是創造一個新的承諾。 當您從then
處理程序返回一個非promise值時,該值是promise的解析值then
返回。 如果你返回一個承諾,那么then
創建的承諾是“奴役的”,以便你返回(等待它解決或拒絕,然后做同樣的事情)。 在評論中你提出了一個非常明智的問題:
如果“then”被異步調用那么這些承諾的輸出順序可能無法預測得對嗎?
小點: then
不是異步調用,它的處理程序 (你傳遞它的函數)是異步調用的。
在一般情況下,是的,這是正確的,你無法預測獨立承諾的順序(那些沒有鏈接在一起的承諾)。 可以預測, 鏈接在一起的承諾(在鏈早期的前后來的處理)。 在你的代碼中,你有三個獨立的鏈(一個用於i = 0,一個用於i = 1,另一個用於i = 2); 每個鏈都有兩個處理器(“1”和“2”)。 所以你知道鏈“i = 0”中的“1”將在同一鏈中的“2”之前發生,但在一般情況下你不知道i = 0
是第一個還是i = 2
一個或其他什么。
但是 ,在這種特定情況下, 可以預測順序(至少在瀏覽器中,也可以在Node.js上),因為每個鏈中的初始承諾開始預先解析,這意味着對其then
處理程序的調用放在microtaskqueue¹立即當你打電話then
。 微任務隊列在每個任務結束時運行(也稱為“macrotask”)。 因此,運行主代碼的任務會立即按順序將回調排隊到每個鏈的“1”處理程序。 當運行該處理程序時,它會將微任務排隊以調用“2 of”處理程序。 所以,由於承諾開始解決,我們知道我們會得到你得到的輸出。 但在一般情況下,你是正確的,你無法預測鏈之間 。
¹ 這是它的網絡術語; JS規范將其稱為PromiseJobs隊列。 更多關於這個答案中的 “微任務”和任務/宏任務。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.