当前位置: 首页 > 知识库问答 >
问题:

无法从异步promise执行器函数中引发错误

那昊
2023-03-14

我一直试图从概念上理解为什么下面的代码没有抓住抛出的代码。如果您从new Promise(async(解决,...部分删除async关键字,那么它工作正常,所以它与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>>");
    // ...
  });

}

这里、这里和这里的答案都重复了“如果你在任何其他异步回调中,你必须使用拒绝”,但是“异步”并不是指异步函数,所以我认为他们的解释不适用于这里(如果他们这样做,我不明白怎么做)。

如果我们使用拒绝代码而不是抛出代码,上面的代码可以正常工作。我想从根本上理解,为什么扔在这里不起作用。谢谢!

共有2个答案

习洲
2023-03-14

因为从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);
    }
  });
}

例如,当您想要执行一些具有方便的异步函数但又需要回调的操作时。下面的人为示例通过使用asyncfs.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
    }
  }
}

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

梁浩
2023-03-14

这是Promise构造函数反模式的异步/等待版本!

切勿将异步函数用作promise执行器函数(即使您可以使其工作1

[1:通过调用解决拒绝而不是使用返回抛出语句]

他们所说的“异步”并不是指async函数,所以我认为他们的解释在这里不适用

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

new Promise(async function() {
    await delay(…);
    throw new Error(…);
})

这相当于

new Promise(function() {
    return delay(…).then(function() {
        throw new Error(…);
    });
})

现在可以清楚地看到,抛出的代码在异步回调中。

Promise构造函数只能捕获同步异常,而async函数从不抛出-它总是返回一个Promise(可能会被拒绝)。并且该返回值被忽略,因为promise正在等待调用resolve

 类似资料:
  • 问题内容: 我一直在试图从概念上理解以下代码为何无法捕获。如果从零件中删除关键字,则它可以正常工作,因此它与Promise执行器是异步函数这一事实有关。 如果代替我们使用,则上面的代码可以正常工作。我想 _从根本_上理解为什么在这里不起作用。谢谢! 问题答案: [1:通过调用而不是使用and 语句] 通过“异步”,它们不是指功能,所以我认为它们的解释在这里不适用 他们也可以。一个简单的例子就 不能

  • 问题内容: 我一直在试图从概念上理解以下代码为何无法捕获。如果从零件中删除关键字,则它可以正常工作,因此它与Promise执行程序是异步函数这一事实有关。 答案重复为:“如果您在任何其他异步回调中,则必须使用”,但是通过“异步”,它们不是在引用函数,因此,我认为它们的解释在此处不适用(如果他们这样做,我不知道怎么做。 如果代替我们使用,上述代码可以正常工作。我想 从根本 上理解为什么在这里不起作用

  • 我有一个异步函数,它将一些数据插入数据库(使用Mariadb)。由于重复的唯一键,此插入可能会失败,因此它会抛出错误(实际上确实如此),但当我尝试再次抛出它以通过Promise捕获它时,它不起作用;它似乎总是以成功的案例结束,即使它抛出了错误。 我尝试改变then/catch顺序,我使用了< code > reject(err);而不是< code >抛出err但是这些都不起作用。 这是POST声

  • 问题内容: 假设我有这段代码 我想知道的是该函数是否将异步执行。 问题答案: 设完成为Call(执行者,未定义,«resolvingFunctions。[[Resolve]],resolvingFunctions。[[Reject]]»)。 如果完成是突然完成,则 令status为Call(resolvevingFunctions。[[Reject]],undefined,«completion。

  • 我正在使用编写promise代码。然后现在,我决定使用wait/async编写它。我在promise中调用了一个函数add_,然后在中调用了另一个函数。然后是该函数的一部分。这是我使用的代码。然后 这是使用wait/async的代码。 使用await/async的代码显示了一个错误,即add\u lessons是意外标识符。那么,告诉我如何在promise中定义异步函数?

  • 我无法在Spring中捕获异步方法抛出的异常。我已经编写了一个未捕获的异常处理程序来捕获,但没有成功。该应用程序将启用启动任意数量的永远运行的异步作业。我认为我的异步方法需要返回Future,以便我可以将其存储在hashmap中并检查其状态或停止作业。我也可以通过存储它来获取所有正在运行的作业。我认为我不能使用get method of Future,因为如果输入正确,它会阻塞,我的作业将永远运行