我正在尝试检查许多条件,如果其中一个条件为真,我想继续执行某个回调函数。否则,我想继续使用不同的回调函数。一些伪代码可能如下所示:
if (condition_1 OR condition_2 OR condition_3) {
on_satisfied()
} else {
on_unsatisfied()
}
但是,检查每个条件都需要一段时间(例如,可能需要数据库查询),所以我想异步检查它们。我还知道,如果其中任何一个返回 TRUE,则我已经满足了我的条件,因此想停止执行并忘记其余条件。为了做到这一点,我想在第一个响应中使用here描述的“肮脏技巧”:抛出一个将在父函数中处理的错误(位于此处的承诺内)
// the function we call if at least one condition is satisfied
function on_satisfied() {
console.log("At least one condition satisfied")
}
// the function we call if no conditions are satisfied
function on_unsatisfied() {
console.log("No conditions satisfied")
}
// a sample condition-checking function
async function check_lessthan_5(to_check, callback_if_not) {
// using a timeout to simulate "slow" checking of conditions;
// the slow checking could be a result of e.g. database queries
await new Promise(r => setTimeout(r, 2000));
if (to_check < 5) {
// throw this error in hopes of terminating parent function,
// because it is sufficient for one condition to be met
// in order for the whole OR-joined expression to be true (we want to stop execution of the parent function)
throw Error("value < 5")
}
return false
}
const all_cond_checker = new Promise((resolve, reject) => {
// store all the resulting promises,
// so when they all resolve we know that no conditions were satisfied
var conditions_list = []
// check all the conditions. In this case, we want to see if any of these numbers is >= 5
for (var i=0; i < 10; ++i) {
// push a resulting promise into the list, we can check later that it resolves
// if the condition is met, terminate this function by propagating error up
conditions_list.push(check_lessthan_5(i)).catch((error) => {resolve()})
}
// once all the promises return, us getting here implies no errors were thrown
// which implies no conditions satisfied
Promise.all(conditions_list).then(reject)
});
问题是,promise 中的
.catch()
似乎没有捕获错误!运行代码,我得到以下结果:
$ node async_test.js
No conditions satisfied
/home/daniel/Signoff-again/node-experiments/async_test.js:20
throw Error("value >= 5")
^
Error: value < 5
at Timeout._onTimeout (/home/daniel/Signoff-again/node-experiments/async_test.js:20:19)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
我对这些结果的解释是,由于某种原因,.catch() 被完全跳过,错误未被处理,
for
循环被破坏,然后 Promise.all() 被执行(因为所有 5 个conditions_list
中的 Promise 已解决),因此调用 on_unsatisfied
函数。相反,我想要/期望的是第一个 on_satisfied
返回后立即调用 check_lessthan_5
函数。
所以问题是:为什么
catch()
在这里似乎不起作用?另外,有更好的方法吗?
提前致谢。
我希望一旦满足第一个条件,返回的错误就会被
.catch()
中的 all_cond_checker
捕获,然后调用 on_satisfied
。我不希望错误一直“传播”出去并在控制台中报告。
预期的控制台输出是:
$ node async_test.js
At least one condition satisfied
你的捕获物放错了地方
async function check_lessthan_5(to_check) {
await new Promise((r) => setTimeout(r, 2000));
if (to_check < 5) {
throw Error('value < 5');
}
return false;
}
const all_cond_checker = new Promise((resolve, reject) => {
var conditions_list = [];
for (var i = 0; i < 10; ++i) {
conditions_list.push(check_lessthan_5(i));
}
Promise.all(conditions_list)
.then((r) => resolve(r))
.catch((err) => reject(err));
});
all_cond_checker
.then((r) => console.log(r))
.catch((err) => console.log(err.message));