提问人:Nawaaz Kortiwala 提问时间:11/13/2023 最后编辑:KaiidoNawaaz Kortiwala 更新时间:11/13/2023 访问量:69
promise rejection 在 then-catch chaining 和 then(resolveCallback, rejectCallback) 之间的工作方式不同
Promise rejection works differently between then-catch chaining and then(resolveCallback, rejectCallback)
问:
总结
此代码表示一个功能,该功能执行 promise 数组,并按解析顺序返回其解析的值。它还包括一个限制器,用于限制可以从给定的 promise 数组中解析的 promise 数量。
约束
如果限制器超过promise数组的长度,则抛出拒绝。 如果任何 promise 抛出错误,则抛出拒绝。 如果已解析的 promise 数量达到限制器值,则按解析的顺序返回已解析的 promise,并忽略其余的 promise。
问题
我有两个不同版本的代码:
v1 - 实现一个 then-catch 链来执行该功能。 v2 - 实现 then,并将 resolve 和 reject 回调作为两个参数。 在 v1 的情况下,即使此承诺列表中的 promise 被拒绝,promise 也会解析而不会引发拒绝。
但是,在 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]
2 版
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时,它说的只是可读性的问题。
我错过了什么?
答:
2赞
Kaiido
11/13/2023
#1
有 2 个主要区别:
.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()
// The Promises's microtasks will be interleaved with these ones
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 都已经解决,所以在使用时,你只会选择已解决的 Promise,并将被拒绝的 Promise 移到列表的末尾,并在你的示例中忽略它。.then().catch()
评论
somePromise
then
resolvedPromiseValues
promise.all