【问题标题】:JavaScript error handling async function passed to reduce [duplicate]JavaScript错误处理异步函数传递给减少[重复]
【发布时间】:2018-01-26 14:41:18
【问题描述】:

我将 async 函数传递给数组 reduce 函数。捕获传入函数抛出的错误的语法是什么?减少发生在 try catch 块内,它可以很好地捕获其他错误,但是如果传入的函数本身抛出错误,节点会给我一个 UnhandledPromiseRejectionWarning。

代码:

aFunction = async (anArray) => {
  try {
    const result = await anArray.reduce(async (a, b) => {
      await doSomethingTo(b);
    }, Promise.resolve());

    return result;
  }

  catch (error) {
    winston.error(error);
  }  
}

(编辑)实际代码:

exports.chainedQueryDB = async (queries, finalTask, download) => {
  let client = await pool.connect();
  try {
    winston.info(`Begin chained table query.`);
    // Loop through query array
    const result = await queries.reduce(async (a, b) => {
      await client.query(b);
    }, Promise.resolve());

    if (download) {
      return streamOut(download, client);
    }

    return result.rows;
  }

  catch (error) {
    throw error;
  }

  finally {
    const final = await client.query(finalTask);
    winston.info(`Temp table dropped.`);
    client.release();
  }
}

(编辑)报告: 用await a; return client.query(b); 替换await client.query(b) 解决了这个问题。仅使用 await client.query(b),reduce 似乎 1) 生成一堆浮动的 client.query 调用,即使早期的承诺被拒绝,这些调用也会全部运行,并且 2) 导致未处理的承诺拒绝警告。使用 await a; return client.query(b); 会在第一次拒绝时停止执行,并且 catch 块会按原意捕获错误。

【问题讨论】:

  • 您希望result 是什么?你为什么使用reduce?您希望doSomething 任务同时发生吗?
  • anArray 是一组需要按顺序发生的 Postgres 查询。 result是最终pg查询操作的结果,返回给调用函数。代码按照编写的方式工作,但模拟数据库错误会导致节点抛出UnhandledPromiseRejectionWarning。
  • 实际上,您问题中的代码确实没有按顺序运行查询,result 始终是undefined。
  • 射击。意外工作的代码是最糟糕的。代码肯定会按顺序执行anArray 中的项目,result 肯定保持我期望的值。我错过了什么?
  • 您向我们展示了您的实际代码吗?什么是doSomething - 也许它会进行一些内部排队?

标签: javascript error-handling async-await try-catch


【解决方案1】:

您还需要对累加器中的承诺(a 参数)做一些事情 - await 它,通过安装 .catch() 回调来处理它的错误,同时等待它与 doSomething(b)。对于顺序执行,您可以这样做

async function aFunction(anArray) {
  try {
    return await anArray.reduce(async (a, b) => {
      await a; // make sure the previous query is done
      return doSomethingTo(b);
    }, Promise.resolve());
  } catch (error) {
    winston.error(error);
  }
}

我会悬停建议不要在这里使用reduce:

async function aFunction(anArray) {
  try {
    let result;
    for (const b of anArray) {
      result = await doSomethingTo(b);
    }
    return result;
  } catch (error) {
    winston.error(error);
  }
}

【讨论】:

  • 答案如何解决问题中描述的问题?
  • @guest271314 它展示了如何避免未处理的拒绝警告。
  • 问题代码和答案代码有什么区别?
  • @guest271314 你看不出有什么不同吗?很明显,它们是两种不同的东西。
  • @sheepgobeep 是的。 (可能是await doSomething(b) 而不是return,这没什么区别)。但是通过等待a,我们不会让a 承诺——前一次迭代的结果——无处可去。也许它有助于在一张纸上写出reduce 的回调和累加器的作用(例如,三个元素的anArray)。
【解决方案2】:

要避免UnhandledPromiseRejectionWarning,您可以将.catch() 链接到aFunction() 调用或利用.then() 的第二个参数来处理被拒绝的Promise 或错误。

或者,将.catch() 链接到doSomethingTo(b) 调用以处理错误。

【讨论】:

    猜你喜欢
    • 2015-12-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 2020-05-15
    • 2020-09-04
    • 2014-05-02
    相关资源
    最近更新 更多