为什么可以尝试捕获async-await呼叫? [英] Why is it possible to try-catch an async-await call?
问题描述
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 onlyfinally
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 await
ed 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屋!