我们有一个并行的承诺调用:-promise.all ((p1, p2)) () .catch ()这里p1,p2是两个不同的promise调用。
- p1 -拒绝某些条件并显示e1
- p2 -拒绝某些条件并显示e2
- p1 -解决然后做某事
- p2 -不解析
p1、p2拒绝条件不同
如果p1,p2都拒绝,我们显示e2
现在假设两个都拒绝,但p1先拒绝,如何处理这个并显示e2 ?
p90 for p1>p2为P90,但如果p1早于p2,则可能存在边缘情况,因此查询
尝试使用promise。allsettle,但它有其他问题,其中p2在。then块运行2次后执行(结果中有2个promise和相应的数组元素)。
我们已经尝试了多种方法,在p1失败的情况下解决一个特定的错误消息,但它不起作用。
前言:承诺这个术语很容易混淆,大多数人都用错了。我的一篇关于术语的博文可能会很有用。)
你看Promise.allSettled
是对的。如果你想在一个承诺实现而另一个承诺被拒绝时做X,这就是你要走的路;你得到一个结果数组,而不是Promise.all
的短路行为,如果任何一个输入承诺被拒绝。
p2 -不解析
这是不清楚你的意思,但如果你的意思是你需要做一些事情,如果p2
没有解决(得到满足或拒绝)在一段时间内,你可能要使用Promise.race
与超时承诺。
没有代码很难帮助你,但这里有一个结合Promise.allSettled
和Promise.race
的例子:
class TimeoutError extends Error {}
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new TimeoutError("timeout"));
}, ms);
});
}
async function test() {
const p1 = // ...get the first promise...
const p2 = // ...get the second promise...
// Wait for the first to settle and the second to either settle or time out
const [result1, result2] = await Promise.allSettled([
p1,
Promise.race([
p2,
timeout(150 /* or whatever, value in milliseconds */)
])
]);
// See what happened
if (result1.status === "fulfilled" && result2.status === "fulfilled") {
// Both promises were fulfilled, see `result1.value` and `result2.value`
} else if (result1.status === "fulfilled") {
if (result2.reason instanceof TimeoutError) {
// The first promise was fulfilled, the second timed out
} else {
// The first promise was fulfilled, the second was rejected
}
} else if (result2.status === "fulfilled") {
// First promise was rejected, second was fulfilled
} else {
// Both promises were rejected, see `result1.reason` and `result2.reason`
}
}
生活的例子:
function f1(ms, fulfill) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (fulfill) {
resolve("1 - OK");
} else {
reject(new Error("1 - failed"));
}
}, ms);
});
}
function f2(ms, fulfill) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (fulfill) {
resolve("2 - OK");
} else {
reject(new Error("2 - failed"));
}
}, ms);
});
}
class TimeoutError extends Error {}
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new TimeoutError("timeout"));
}, ms);
});
}
async function example(ms1, fulfill1, ms2, fulfill2, msTimeout) {
const p1 = f1(ms1, fulfill1);
const p2 = f2(ms2, fulfill2);
// Wait for the first to settle and the second to either settle or time out
const [result1, result2] = await Promise.allSettled([
p1,
Promise.race([p2, timeout(msTimeout)])
]);
// See what happened
if (result1.status === "fulfilled" && result2.status === "fulfilled") {
console.log(`Both promises were fulfilled:`);
console.log(`result1.value = ${result1.value}`);
console.log(`result2.value = ${result2.value}`);
} else if (result1.status === "fulfilled") {
if (result2.reason instanceof TimeoutError) {
console.log(`The first promise was fulfilled, the second timed out`);
console.log(`result1.value = ${result1.value}`);
console.log(`result2 was a timeout`);
} else {
console.log(`The first promise was fulfilled, the second was rejected`);
console.log(`result1.value = ${result1.value}`);
console.log(`result2.reason = ${result2.reason}`);
}
} else if (result2.status === "fulfilled") {
console.log(`The first promise was rejected, second was fulfilled`);
console.log(`result1.reason = ${result1.reason}`);
console.log(`result2.value = ${result2.value}`);
} else {
// Both promises were rejected, see `result1.reason` and `result2.reason`
console.log(`The first promise was rejected, second was fulfilled`);
console.log(`result1.reason = ${result1.reason}`);
console.log(`result2.rason = ${result2.reason}`);
}
}
function test(label, ms1, fulfill1, ms2, fulfill2, msTimeout) {
console.log(`${label}:`);
example(ms1, fulfill1, ms2, fulfill2, msTimeout)
.catch((error) => {
console.error(`Unexpected error in test: ${error.stack ?? String(error)}`);
});
}
const onClick = (id, fn) => document.getElementById(id).addEventListener("click", fn);
onClick("both-fulfill", () => test("Both Fulfill", 100, true, 150, true, 200));
onClick("first-fulfills", () => test("First Fulfills", 100, true, 150, false, 200));
onClick("second-times-out", () => test("Second Times Out", 100, true, 250, true, 200));
onClick("second-fulfills", () => test("Second Fulfills", 100, false, 150, true, 200));
onClick("both-reject", () => test("Both Reject", 100, false, 150, false, 200));
<input type="button" id="both-fulfill" value="Both Fulfill">
<input type="button" id="first-fulfills" value="First Fulfills">
<input type="button" id="second-times-out" value="Second Times Out">
<input type="button" id="second-fulfills" value="Second Fulfills">
<input type="button" id="both-reject" value="Both Reject">