[英]Troubles with promise array and async functions
我試圖使用異步函數來實現 Promise.all 函數。 但是當其中一個承諾被拒絕時,我得到一個錯誤。 這是我所做的實現:
async function Promise_All_II(promises){
let results = []
for(let p of promises)
results.push(await p)
return results
}
const takeTime = (value, time=1000) => new Promise(resolve => setTimeout(resolve, time, value))
let promises = [
Promise.resolve(1),
takeTime(2),
Promise.reject('You are fairly dump'),
takeTime(3)
]
console.log('Promise all II:')
Promise_All_II(promises).then(console.log, console.log)
這是當其中一個承諾被拒絕時我得到的錯誤:
Promise all II:
(node:9399) UnhandledPromiseRejectionWarning: You are fairly dump
(node:9399) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:9399) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
You are fairly dump
(node:9399) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
我試圖用 try-catch 包裝for 循環,但它沒有用。 我還嘗試在p之后放置和.catch ,但仍然沒有用。
我注意到當您嘗試執行以下操作時會發生相同的錯誤:
let f = async () => {
let ps = [
Promise.resolve(10),
Promise.reject(10),
Promise.resolve(11),
Promise.resolve(12)
]
for(let p of ps)
await p
}
f().catch(v =>
console.log('something happened')
)
有人能幫助我嗎?
在 nodejs 中,當解釋器返回事件循環時,如果您將被拒絕的 Promise 留在沒有.catch()
處理程序的地方,您將收到有關未處理拒絕的錯誤。 這意味着您不能在await
某個其他承諾時將被拒絕的承諾留在變量中。 這將觸發未處理的拒絕錯誤。 JS 解釋器不夠聰明,無法知道您稍后會收到拒絕。
所以,當你這樣做時:
results.push(await p)
並且,任何其他 Promise 被拒絕,您將得到未處理的拒絕,因為被拒絕的 Promise 在它拒絕時沒有處理程序來處理拒絕,並且await
會導致解釋器返回事件循環。 解釋器看到你處於空閑狀態,一個承諾被拒絕並且它沒有拒絕處理程序,從而觸發錯誤。
因此,由於未處理的拒絕在 nodejs 中的工作方式,實際上沒有辦法像您嘗試使用await
和for
循環那樣實現這一點,因為這使得其他承諾在await
期間沒有拒絕處理程序。
Promise.all()
的通常實現包括創建您自己的 Promise 並使用計數器來跟蹤所有問題何時解決。 而且,您會立即在每個 Promise 上安裝 resolve 和 reject 處理程序,這樣它們就不會處於導致未處理的拒絕處理程序的狀態。
這是Promise.all()
的簡單實現,您可以在此代碼段中運行它:
function Promise_All_II(promises) { return new Promise((resolve, reject) => { let cntr = 0; let length = 0; let results; for (let p of promises) { // keep track of index, for later use with result let i = length++; Promise.resolve(p).then(val => { results[i] = val; ++cntr; if (cntr === length) { resolve(results); } }).catch(reject); } if (length === 0) { resolve([]); return; } results = new Array(length); }); } const takeTime = (value, time=1000) => new Promise(resolve => setTimeout(resolve, time, value)) let promises = [ Promise.resolve(1), takeTime(2), Promise.reject('You are fairly dump'), takeTime(3) ]; console.log('Promise all II:') Promise_All_II(promises).then(console.log, console.log);
這會立即在每個 Promise 上安裝 resolve 和 reject 處理程序,從而避免未處理的拒絕錯誤。
注意, Promise_All_II()
的調用者還必須有一個拒絕處理程序。
需要注意的幾個細節:
Promise.all()
規范的數組。 它甚至不必具有.length
屬性。Promise.all()
規范,這實現了“快速拒絕”(例如,一旦任何承諾拒絕就拒絕)。Promise.all()
規范,這允許非承諾值在可迭代中。 這就是我們使用Promise.resolve(p).then(...)
的原因,因此任何普通值都會被包裝,然后我們可以將其視為承諾。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.