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.