javascript – 为什么尝试捕获async-await调用是可能的?

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中的错误,因为在稍后阶段调用回调以及try-catch不再可见的上下文.

现在在JavaScript中使用生成器,承诺和协程实现aync-await,如下所示:

// 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就可以工作了,这通常被称为异步等待回调的一大优势.

捕捞的原因和方式如何?当其中一个asyncTask调用导致promise拒绝时,coroutine aka async如何设法将错误抛出到try-catch中?

编辑:正如其他人已经指出的那样,JavaScript引擎实现await运算符的方式可能与像Babel这样的转换器使用的纯JavaScript实现非常不同,并且在上面作为协程示例显示.因此更具体一点:这是如何使用本机JavaScript的?

最佳答案

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

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

>它可以像普通表达式一样评估结果值
>它可以像throw语句一样进行求值,从而导致异常
>它可以像return语句一样进行求值,在结束函数之前只导致finally语句被计算

在挂起的发电机上,可以通过调用.next(),.throw().return()方法来实现. (当然还有第四种可能的结果,永远不会恢复).

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

等待的值将是Promise.resolve()d到一个promise,然后.then() method被调用它有两个回调:当promise履行时,coroutine恢复正常值(promise结果),并且当promise拒绝,coroutine突然完成恢复(例外 – 拒绝原因).

您可以查看co库代码或转换器输出 – 它实际上是calls gen.throw from the promise rejection callback.

点赞