【问题标题】:Error handling in a Promise.all like flow in async/await syntaxPromise.all 中的错误处理类似于异步/等待语法中的流
【发布时间】:2017-09-19 23:59:08
【问题描述】:

我有一些问题需要以“并行”方式处理多个拒绝。 当我们“并行等待”时如何处理异步函数中的拒绝。
这里是一个例子:

function in_2_sec(number) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('Error ' + number);
        }, 2000);
    }) 
}

async function f1() {
    try {
        let a = in_2_sec(3);
        let b = in_2_sec(30);
        return await a + await b; // awaiting in "parallel"
    } catch(err) {
        console.log('Error', err);
        return false;
    }
}

async function f2() {
    try {
        let a = await Promise.all([in_2_sec(3), in_2_sec(30)]);
        return a[0] + a[1];
    } catch(err) {
        console.log('Error', err);
        return false;
    }
}

// f1().then(console.log) // UnhandledPromiseRejectionWarning
// f2().then(console.log) // Nice


f1() 在节点中创建UnhandledPromiseRejectionWarning,因为第二次拒绝(b)没有处理。
f2() 完美运行,Promise.all() 可以解决问题,但是如何使用仅 async/await 语法而不使用 Promise.all() 来制作 f2()

【问题讨论】:

  • await "等待承诺解决"。在f1 中,您正在等待每个承诺独立解决,因为您使用了两次await。由于您根本不处理它们,因此行为是合乎逻辑的。
  • @Sebas:确实。我认为问题是如何优雅地处理这种逻辑行为...... :-)
  • @Sebas 确定这是完全合乎逻辑的,并且作为 T.J.克劳德说这个问题即将在没有Promise.all()的情况下处理这种行为。
  • 哇,这个问题真的让我陷入了一个循环,直到我意识到第二个 await 根本没有执行。

标签: javascript node.js asynchronous async-await


【解决方案1】:

f2() 完美运行,Promise.all() 可以解决问题,但是如何使用仅 async/await 语法而不使用 Promise.all() 来制作 f2()

一点也不。 使用Promise.all 这就是它的用途。不要想到 async/await 替换承诺 - 你仍然在使用它们,它只是 then 调用的语法糖。 Promise.all 没有语法替换。

当然也可以自己重新实现Promise.all 的行为(依赖于Promise 构造函数和.then 原语),但你真的不想这样做(有太多陷阱)。

【讨论】:

  • Promise.all() 的问题是它只返回一个reject。换句话说,如果有超过 1 个 Promise 被拒绝,我们将无法处理所有拒绝。只会返回第一个拒绝。
  • @NgHuiXiong 如果你想处理并行代码中的所有错误,你必须在每个 promise 被传递给Promise.all之前单独处理拒绝。
【解决方案2】:

我能想到但我不喜欢的最简单的方法是在错误路径中对catch 进行无条件调用,可能使用实用程序函数。

使用这些实用功能:

function noop() {
}

function markHandled(...promises) {
    promises.forEach(p => p && p.catch(noop));
}

是:

async function f2() {
    let a, b;
    try {
        a = in_2_sec(3);
        b = in_2_sec(30);
        return await a + await b;
    } catch(err) {
        console.log('Error', err);
        markHandled(a, b);
        return false;
    }
}

这样,我们明确地忽略了我们不关心的拒绝,发现了主要错误。

例子:

function in_2_sec(number) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('Error ' + number);
        }, 2000);
    }) 
}

function noop() {
}

function markHandled(...promises) {
    promises.forEach(p => p && p.catch(noop));
}

async function f2() {
    let a, b;
    try {
        a = in_2_sec(3);
        b = in_2_sec(30);
        return await a + await b;
    } catch(err) {
        console.log('Error', err);
        markHandled(a, b);
        return false;
    }
}

f2().then(console.log);

【讨论】:

  • 没想到。谢谢。我不确定是否有更优雅的方式。我现在会坚持使用Promise.all
  • @Smirow:是的。有 some talk 关于添加到 await 来处理这样的事情。
  • @Smirow:如果这回答了您的问题,Stack Overflow 的工作方式,您可以通过单击它旁边的复选标记“接受”答案,这会将其取消未回答的问题清单; details here.
猜你喜欢
  • 2018-07-29
  • 2018-11-12
  • 2019-03-01
  • 2020-06-29
  • 2020-05-24
  • 1970-01-01
  • 2022-01-09
  • 2018-04-06
  • 2021-09-18
相关资源
最近更新 更多