为什么可以尝试捕获async-await呼叫? [英] Why is it possible to try-catch an async-await call?

查看:132
本文介绍了为什么可以尝试捕获async-await呼叫?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JavaScript中有一个常见的反模式:

There is a common anti pattern in JavaScript:

function handleDataClb(err, data) {
    if(!data) throw new Error('no data found');
    // handle data... 
} 

function f() {
    try {
        fs.readFile('data', 'utf8', handleDataClb);
    } catch(e) {
        // handle error... 
    }
}

f 中的try-catch不会在 handleDataClb 中捕获错误

This try-catch in f will not catch errors in the handleDataClb as the callback is called in a later stage and context where the try-catch is not visible anymore.

现在,JavaScript async-await中的生成器使用生成器,promise和协程来实现。 ,例如:

Now in JavaScript async-await is implemented using generators, promises, and coroutines, as in:

// coroutine example 
co(function* doTask() {
    try {
        const res1 = yield asyncTask1(); // returns promise
        const res2 = yield asyncTask2(); // returns promise
        return res1 + res2;
    } catch(e) {
        // handle error... 
    }
});

// async-await example
async function doTask() {
    try {
        const res1 = await asyncTask1(); // returns promise
        const res2 = await asyncTask2(); // returns promise
        return res1 + res2;
    } catch(e) {
        // handle error... 
    }
}

这种try-catch的工作方式,通常被称为异步等待优于回调的一大优势。

This way the try-catch works, which is often mentioned as one great advantage of async-await over callbacks.

为什么和捕获如何工作?当 asyncTask 之一调用时,协整程序又名 async 如何将错误抛出try-catch中

Why and how does the catch work? How does the coroutine aka async manage to throw the error inside the try-catch when one of the asyncTask calls results in a promise rejection?

编辑:正如其他人指出的那样,JavaScript引擎如何实现 await 运算符的方式与像Babel这样的编译器使用的纯JavaScript实现非常不同,上面的代码显示为协程示例。因此,更具体地说:如何使用本机JavaScript进行工作?

as others have pointed out, the way how the JavaScript engine implements the await operator can be very different from the pure JavaScript implementation used by transpilers like Babel and shown above as coroutine example. Therefore to be more specific: how is this working using native JavaScript?

推荐答案


为什么捕获工作?协程又名异步如何将错误抛出try-catch中?

Why and how does the catch work? How does the coroutine aka async manage to throw the error inside the try-catch?

A yield code>或 await 表达式可以有3种不同的结果:

A yield or await expression can have 3 different outcomes:


  • 它可以像普通表达式一样求值到

  • 它可以像 throw 语句一样求值,从而引起异常

  • 它可以像 return 语句那样进行求值,仅导致 finally 语句被求值在结束函数之前

  • It can evaluate like a plain expression, to the result value of that
  • It can evaluate like a throw statement, causing an exception
  • It can evaluate like a return statement, causing only finally statements to be evaluated before ending the function

在挂起的生成器上,可以通过调用 .next() .throw () .return() 方法。 (当然,还有第四种可能的结果,永远都不会恢复。)

On a suspended generator, this can be achieved by calling either the .next(), .throw() or .return() methods. (Of course there's also a 4th possible outcome, to never get resumed).


…当asyncTask调用之一导致承诺被拒绝时?

…when one of the asyncTask calls results in a promise rejection?

等待的值将是 Promise .resolve()到承诺,然后 .then()方法通过两个回调对其进行调用:当promise满足时,协程将以常规方式恢复值(承诺结果),并且当承诺被拒绝时,协程会突然完成(异常-拒绝原因)。

The awaited value will be Promise.resolve()d to a promise, then the .then() method gets invoked on it with two callbacks: when the promise fulfills, the coroutine is resumed with a normal value (the promise result), and when the promise rejects, the coroutine is resumed with an abrupt completion (exception - the rejection reason).

您可以查看库代码或transpiler输出-从字面上调用 gen.throw 来自承诺拒绝回调

You can look at the co library code or the transpiler output - it literally calls gen.throw from the promise rejection callback.

这篇关于为什么可以尝试捕获async-await呼叫?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆