不能从异步承诺执行程序函数中抛出错误

4 javascript node.js promise async-await

我一直试图理解为什么下面的代码没有抓住它throw.如果asyncnew Promise(async (resolve, ...部件中删除关键字,那么它可以正常工作,因此它与Promise执行程序是异步函数的事实有关.

(async function() {

  try {
    await fn();
  } catch(e) {
    console.log("CAUGHT fn error -->",e)
  }

})();

function fn() {

  return new Promise(async (resolve, reject) => {
    // ...
    throw new Error("<<fn error>>");
    // ...
  });

}
Run Code Online (Sandbox Code Playgroud)

这里的答案,这里这里重复一遍"如果你在任何其他异步回调中,你必须使用reject",但是"异步"它们并不是指async函数,所以我认为它们的解释不适用于此(如果他们这样做,我不明白如何).

如果不是throw我们使用reject,上面的代码工作正常.从根本上说,我想明白为什么throw不在这里工作.谢谢!

Ber*_*rgi 12

这是Promise构造函数antipattern的async/await版本!

从来没有 使用async function作为一个Promise执行程序功能(即使你可以把它工作1)!

[1:通过电话resolvereject不是使用returnthrow声明]

通过"异步"它们并不是指async功能,所以我不认为它们的解释适用于此

他们也可以.一个无法工作的简单例子是

new Promise(async function() {
    await delay(…);
    throw new Error(…);
})
Run Code Online (Sandbox Code Playgroud)

这相当于

new Promise(function() {
    return delay(…).then(function() {
        throw new Error(…);
    });
})
Run Code Online (Sandbox Code Playgroud)

现在很清楚,它throw是在异步回调中.

Promise构造也只能望尘莫及同步异常,和一个async function 不会抛出 -它总是会返回一个承诺(这可能会虽然被拒绝).并且返回值被忽略,因为承诺正在等待resolve被调用.

  • 未来的搜索者应该看到 [this follow up question](http://stackoverflow.com/questions/43084557/using-promises-to-await-triggered-events) 了解更多关于 Promise 反模式的信息。 (2认同)

Cas*_*sey 6

因为从 Promise 执行器内部与外界“通信”的唯一方法是使用resolvereject函数。您可以使用以下内容作为示例:

function fn() {
  return new Promise(async (resolve, reject) => {
    // there is no real reason to use an async executor here since there is nothing async happening
    try {
      throw new Error('<<fn error>>')
    } catch(error) {
      return reject(error);
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

一个例子是,当您想做一些具有方便的异步函数但也需要回调的事情时。以下人为示例通过使用fs.promises.readFile带有基于回调的函数的异步fs.writeFile函数读取文件来复制文件。在现实世界中,您永远不会混合fs这样的功能,因为没有必要。但有些库(例如 stylus 和 pug)使用回调,并且我在这些场景中一直使用类似的东西。

const fs = require('fs');

function copyFile(infilePath, outfilePath) {
  return new Promise(async (resolve, reject) => {
    try {
      // the fs.promises library provides convenient async functions
      const data = await fs.promises.readFile(infilePath);
      // the fs library also provides methods that use callbacks
      // the following line doesn't need a return statement, because there is nothing to return the value to
      // but IMO it is useful to signal intent that the function has completed (especially in more complex functions)
      return fs.writeFile(outfilePath, data, (error) => {
        // note that if there is an error we call the reject function
        // so whether an error is thrown in the promise executor, or the callback the reject function will be called
        // so from the outside, copyFile appears to be a perfectly normal async function
        return (error) ? reject(error) : resolve();
      });
    } catch(error) {
      // this will only catch errors from the main body of the promise executor (ie. the fs.promises.readFile statement
      // it will not catch any errors from the callback to the fs.writeFile statement
      return reject(error);
      // the return statement is not necessary, but IMO communicates the intent that the function is completed
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

显然每个人都说这是一种反模式,但当我想在做一些只能通过回调完成的事情之前做一些异步的事情时,我总是使用它(不是像我设计的例子那样复制文件)。我不明白为什么人们认为这是一种反模式(使用异步承诺执行器),并且还没有看到一个例子来说服我它应该被接受为一般规则。


归档时间:

查看次数:

1916 次

最近记录:

8 年,8 月 前