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

如何从异步函数抛出异常

谢旭
2023-03-14

我有一个异步函数,我希望在失败时抛出异常。然而,似乎有一些东西阻止了这一点:

通过省略try catch块,我希望抛出一个异常,我想在函数外部处理这个异常。

我得到的实际结果有点令人困惑:

(节点:10636)未处理的Promiser弹出警告:未处理的promise拒绝(拒绝id:1):E11000重复键错误索引。

(node: 10636)DeprecationWarning:未处理的promise拒绝已弃用。将来,未处理的promise拒绝将使用非零退出代码终止Node.js进程。

async f(obj) {
    await db.collection('...').save(obj);
}

当我尝试捕获异常并抛出其他东西时,会得到相同的结果:

async f(obj) {
    try {
        await db.collection('...').save(obj);
    } catch(e) {
        throw e.message;
    }
}

该函数是从try块调用的,因此看不到这如何是未处理的promise。

我正在尝试使用< code>f作为另一个函数的参数:

g(obj, handler) {
    try {
        handler(obj);
    } catch(e);
        ...
    }
}

g(objToSave, f);

共有3个答案

通宾白
2023-03-14

我想在函数之外处理它

这是你唯一忘记做的事情(这就是为什么警告抱怨未经处理的拒绝)。您的函数 f 工作正常。

您无法从异步函数中引发同步异常,一切都是异步的,异常将导致结果promise被拒绝。这就是您需要捕获的内容:

function g(obj, handler) {
    try {
        Promise.resolve(handler(obj)).catch(e => {
            console.error("asynchronous rejection", e);
        });
    } catch(e) {
        console.error("synchronous exception", e);
    }
}
// or just
async function g(obj, handler) {
    try {
        await handler(obj);
//      ^^^^^
    } catch(e) {
        console.error("error", e);
    }
}

g(objToSave, f);
洪飞驰
2023-03-14

最终,您要做的是在同步函数g中调用异步函数f,这将不起作用(这相当于能够将异步函数转换为同步函数)。

相反,g要么也必须是async,要么它应该正确处理f返回的Promise。但是,在本评论中,您声明f表示的函数可能并不总是返回Promise,在这种情况下,前一个选项最容易实现:

async g(obj, handler) {
  return await handler(obj);
}

如果处理程序不返回promise,而只返回一个值(此处已记录),这也将起作用。

调用< code>g(再次)需要异步函数或代码来处理其返回的promise:

g(objToSave, f).then(...).catch(...)
凌蕴藉
2023-03-14
async f(obj) {
    try {
        await db.collection('...').save(obj);
    } catch(e) {
        throw e.message;
    }
}

该函数是从try块调用的,因此看不到这如何是未处理的promise。

这里未处理的是对由< code>f()函数返回的promise的拒绝,而不是由< code >返回的promise。save()方法。所以这不会导致问题:

async f(obj) {
    try {
        await db.collection('...').save(obj);
    } catch(e) {
        console.error(e.message);
    }
}

在异步函数中引发异常总是拒绝该函数返回的promise。

要捕获异常,您必须在另一个异步函数中执行此操作:

try {
    asyncFunc();
} catch (err) {
    // you have the error here
}

或者,您可以显式添加拒绝处理程序:

asyncFunc().catch(err => {
    // you have the error here
});

如果您捕获异常并抛出另一个异常,那么您会遇到相同的问题,只是在不同的函数中。

您必须添加一个promise拒绝处理程序,并且不抛出异常或返回被拒绝的promise——或者在另一个处理异常的异步函数中运行该函数,而不是重新抛出相同或新的异常。

总而言之:每个<code>异步

拒绝处理程序是使用双函数. then(). catch()try{wait asyncFunction();}catch(err){…}添加的

当您在没有拒绝处理程序的情况下拒绝promise时,您将在旧版本的Node中收到警告,在新版本的Node中收到致命错误-有关更多详细信息,请参阅此答案:

  • 我是否应该避免异步处理promise拒绝?
 类似资料:
  • 问题内容: 如何从异步函数返回值?我试图喜欢这个 它给了我, 问题答案: 您不能超出范围。为了获得预期的结果,您应该将其包装到异步IIFE中,即 样品。 有关更多信息 由于返回一个Promise,因此可以将其省略,如下所示: 然后像以前一样做

  • 问题内容: 如何从异步函数返回值?我试图喜欢这个 它给了我, 问题答案: 您不能超出范围。为了获得预期的结果,您应该将其包装到异步IIFE中,即 样品。 有关更多信息 由于返回一个Promise,因此可以将其省略,如下所示: 然后像以前一样做

  • 在你可以捕获异常之前,一些代码必须抛出一个异常。任何代码都可能会抛出异常:您的代码,来自其他人编写的包(例如Java平台附带的包)或Java运行时环境的代码。无论是什么引发的异常,它总是通过 throw 语句抛出。 您可能已经注意到,Java平台提供了许多异常类。所有类都是Throwable类的后代,并且都允许程序区分在程序执行期间可能发生的各种类型的异常。 您还可以创建自己的异常类来表示在您编写

  • 在Javascript中的异步生成器函数中,第一个参数本身就是一个异步生成器函数,该函数用于转换函数。在函数中有一个转换和一个检查。如果检查不正确,应中止发电机功能。如果检查正确,则应得出结果。我用随机数模拟了误差。 我找到了三种抛出错误的方法: 返回Promise.reject(新的错误(一些消息); 抛出新的错误(一些消息。); 产生Promise.reject(新的错误(一些消息); 所有的

  • 我知道如何创建对具有参数并返回的方法的引用,它是: 但是,如果函数抛出异常(假设它被定义为: 我如何定义这个引用?

  • 我知道JVM有一个异常表,它映射在给定字节码索引中可以抛出的可能异常。我还读到athrow字节码抛出了堆栈顶部存在的引用类型的exception。我的问题更多地涉及像irem这样的指令如何“抛出”异常。 JVM是否会在每次指令执行后检查堆栈的顶部,以检查是否存在异常?如果你能洞察到这件事的话,你会很感激的。