Promise 拒绝在 then-catch 链接和 then(resolveCallback,rejectCallback) 之间的工作方式不同

问题描述 投票:0回答:2

总结

此代码表示执行一系列 Promise 并按照解析顺序返回其“解析值”的功能。它还包括一个限制器,用于限制可以从给定的 Promise 数组中解析的 Promise 的数量。

限制

如果限制器超过了 Promise 数组的长度,则抛出拒绝。 如果任何 Promise 抛出错误,则抛出拒绝。 如果已解决的 Promise 数量达到限制值,则按其解决顺序返回已解决的 Promise,并忽略其余的 Promise。

问题

我有两个不同版本的代码:

v1 - 实现 then-catch 链来执行功能。 v2 - 实现 then ,并将解析和拒绝回调作为两个参数。 在 v1 的情况下,即使此承诺列表中的承诺被拒绝,承诺也不会引发拒绝。

但是,在 v2 的情况下,代码按预期工作,即,当任何 Promise 拒绝时,它会抛出拒绝。

代码

v1

async function somePromises(promises, promisesToWait) { // Throws error if promises to wait for is greater than promises in the `promise` array if (promisesToWait > promises.length) { return Promise.reject("Count is greater than the number of promises"); } return await new Promise((resolve, reject) => { const resolvedPromiseValues = []; // stores the values of resolved values let hasRejected = false; // tracks the rejection promises.forEach((promise) => { promise() .then((resolvedValue) => { // Does not execute if rejected. SOMEHOW, NOT WORKING in v1 if (hasRejected) return; if (resolvedPromiseValues.length < promisesToWait) { resolvedPromiseValues.push(resolvedValue); if (resolvedPromiseValues.length === promisesToWait) { resolve(resolvedPromiseValues); } } }) .catch((error) => { if (!hasRejected) { hasRejected = true; } reject(error); }); }); }); } const rejectablePromises = [ () => Promise.resolve(1), () => Promise.resolve(2), () => Promise.reject("I will reject"), () => Promise.resolve(3), ]; async function main() { somePromises(rejectablePromises, 3).then(console.log).catch(console.error); } main(); // Expected output: I will reject // Actual output: [1, 2, 3]


v2

async function somePromises(promises, promisesToWait) { // Throws error if promises to wait for is greater than promises in the `promise` array if (promisesToWait > promises.length) { return Promise.reject("Count is greater than the number of promises"); } return await new Promise((resolve, reject) => { const resolvedPromiseValues = []; // stores the values of resolved values let hasRejected = false; // tracks the rejection promises.forEach((promise) => { promise().then( (resolvedValue) => { // Should not execute if rejected. WORKS AS EXPECTED in v2 if (hasRejected) return; if (resolvedPromiseValues.length < promisesToWait) { resolvedPromiseValues.push(resolvedValue); if (resolvedPromiseValues.length === promisesToWait) resolve(resolvedPromiseValues); } }, (error) => { if (!hasRejected) { hasRejected = true; } reject(error); } ); }); }); } const rejectablePromises = [ () => Promise.resolve(1), () => Promise.resolve(2), () => Promise.reject("I will reject"), () => Promise.resolve(3), ]; async function main() { somePromises(rejectablePromises, 3).then(console.log).catch(console.error); } main(); // Expected output: I will reject // Actual output: I will reject

这两个实现承诺有区别吗?我阅读了文档,但找不到两者之间的任何清晰度。问 ChatGPT,它说这只是可读性问题。

我错过了什么?

javascript promise
2个回答
0
投票

    .then(a).catch(b)
  • 将处理
    a
    执行过程中抛出的错误,而
    .then(a, b)
    则不会:
    
    

Promise.resolve(1) .then(() => { throw "bad" }) .catch((err) => console.log("caught in .catch()")); Promise.resolve(1) .then(() => { throw "bad" }, (err) => console.log("caught in .then()"));

    .then(a).catch(b)
  • 将跨越两个微任务:一个来自
    then()
    ,另一个来自
    .catch()
    :
    
    

queueMicrotask(() => { console.log("microtask 1"); queueMicrotask(() => { console.log("microtask 2"); queueMicrotask(() => { console.log("microtask 3"); }); }); }); Promise.reject("bad") .then(() => { }) .catch((err) => console.log("caught in .catch()")); Promise.reject("bad") .then(() => { }, (err) => console.log("caught in .then()"));

虽然您可能要记住第一个区别,但您的问题是由第二个区别引起的。由于您的所有 Promise 都已解决,因此在使用

.then().catch()

时,您将仅选择已解决的 Promise,并将拒绝的 Promise 移至列表末尾,并在示例中实际忽略它。

    


-1
投票

forEach 不会等待 Promise 解决或拒绝。

意思是,如果您将 forEach 与 then catch 一起使用,则 catch 块将无法知道 Promise 是否失败或通过,它只是通过。 但是在第二种情况下,由于您对成功和错误使用了不同的回调,因此即使稍后拒绝 Promise 但它也会被捕获。

我也从 chatGPT 询问了这些问题,这里是对话链接。

聊天 GPT 对话

© www.soinside.com 2019 - 2024. All rights reserved.