【发布时间】:2019-02-25 07:18:13
【问题描述】:
在 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 中,异步等待是使用生成器、承诺和协程实现的,如下所示:
// 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 以这种方式工作,这通常被认为是 async-await 优于回调的一大优势。
catch 为什么以及如何工作?当asyncTask 调用之一导致promise 拒绝时,协程又名async 如何设法在try-catch 中抛出错误?
编辑:正如其他人所指出的,JavaScript 引擎实现 await 运算符的方式可能与 Babel 等转译器使用的纯 JavaScript 实现非常不同,上面显示为 coroutine example。因此更具体地说:使用本机 JavaScript 是如何工作的?
【问题讨论】:
-
在高层次上,这就是语言如何协调被拒绝的承诺,因为没有更好的方法来处理它们。使用它们作为返回值只会让事情变得奇怪。如果您想阅读规范,这里有一些不错的地方。 tc39.github.io/ecma262/#await-rejected 。和tc39.github.io/ecma262/#sec-throwcompletion
-
感谢您的链接!据我了解,JS 引擎当然可以做各种魔术来实现这样的规范。但是纯 JS 协程实现也能达到同样的效果,应该可以用 JS 语法来解释吧?
标签: javascript ecmascript-6 error-handling async-await coroutine