consumerFunction
(运行时间根据传入的记录而变化很大)并返回已解决承诺的列表。
消费记录:
exports.consumeRecords = async (args) => {
let { records, consumerFunction } = args
let settledPromises = await Promise.allSettled(
records.map(async (record, i) => {
return consumerFunction(record)
.then(async (result) => {
console.log(`${thisTaskName} consumer function returned :>> `, result)
return Promise.resolve(result)
})
.catch(async (err) => {
console.error(`${thisTaskName} consumer function error ${err}`)
return Promise.reject("ERR: ", err)
})
})
)
return settledPromises
}
为了测试这个,我正在使用 Jest 测试。我有一个模拟消费者函数,mockAsyncConsumerFunction
,它在每次返回时都设置了延迟......要么是已解决的承诺,要么是被拒绝的承诺。我希望能够测试所有的承诺是否会并行运行,直到完成。
test("When a function rejects lst, the promises still all settle", async () => {
function delay(t, v) {
return new Promise((resolve) => setTimeout(resolve, t, v))
}
let mockAsyncConsumerFunction = async (recordBody) => {
if (recordBody.fake === 111) {
return delay(30, Promise.resolve("111 returned"))
} else if (recordBody.fake === 222) {
return delay(20, Promise.resolve("222 returned"))
} else {
return delay(10, Promise.reject("333 error!"))
}
}
let returnedPromise = await utils.consumeRecords({
consumerFunction: mockAsyncConsumerFunction,
records: [{ fake: 111 }, { fake: 222 }, { fake: 333 }]
})
expect(returnedPromise).toStrictEqual([
{ status: "fulfilled", value: "111 returned" },
{ status: "fulfilled", value: "222 returned" },
{ reason: "ERR: ", status: "rejected" },
])
})
这次测试的结果是
[UnhandledPromiseRejection: 此错误源自于抛出 在没有 catch 块的异步函数内部,或者通过拒绝 未使用 .catch() 处理的承诺。承诺被拒绝 “333 错误!”的原因。] { 代码:'ERR_UNHANDLED_REJECTION' }注意,承诺正在拒绝我希望它拒绝的价值。我在 forEach 的消费者函数调用中有一个 '.catch()',但它似乎没有捕捉到错误。
编辑:当我将 consumeRecords 函数中的
return Promise.reject('ERR: ', err)
行更改为
return err
时,我仍然遇到相同的错误。EDIT2:当我在延迟函数的末尾添加
.catch(()=>null)
时,我不再收到“未处理的拒绝”错误......但我的 Jest 测试和 settledPromises 数组中仍然收到“抛出”消息通过拒绝被“满足”(即:我基本上只是解决而不是拒绝)
Promise.resolve()
的值为
Promise.reject('msg')
会导致未处理的拒绝。第一条评论(投票 4 次)说这是返回 Promise.reject() 的结果是不正确的。因此我将延迟功能更改为:
async function delay(t, v) {
return new Promise((resolve, reject) => {
if(typeof v ==='string') {
return setTimeout(reject, t, v)
} else {
return setTimeout(resolve, t, v)
}
})
}
我的 mockAsyncConsumerFunction 对此:
let mockAsyncConsumerFunction = async (recordBody) => {
if (recordBody.fake === 111) {
return delay(30, Promise.resolve("111 returned"))
} else if (recordBody.fake === 222) {
return delay(20, Promise.resolve("222 returned"))
} else {
return delay(10, "333 error!") //changed from Promise.reject("333 error!")
}
}