为什么ES2017引入async/await,而ES6已经有了生成器?

3

当阅读关于asyncawait的内容时,我注意到它几乎与生成器函数等价。请考虑《TypeScript深度探索》中的这个片段

Async Await

(...)

// Not actual code. A thought experiment
async function foo() {
    try {
        var val = await getMeAPromise();
        console.log(val);
    }
    catch(err) {
        console.log('Error: ', err.message);
    }
}

(...)

Generated JavaScript

You don't have to understand this, but it's fairly simple if you've read up on generators. The function foo can be simply wrapped up as follows:

const foo = wrapToReturnPromise(function* () {
    try {
        var val = yield getMeAPromise();
        console.log(val);
    }
    catch(err) {
        console.log('Error: ', err.message);
    }
});

where the wrapToReturnPromise just executes the generator function to get the generator and then use generator.next(), if the value is a promise it would then+catch the promise and depending upon the result call genertor.next(result) or genertor.throw(error). That's it!

为什么最终成为“新功能”的原因是什么?在我看来,只需使用某些库中的“wrapToReturnPromise”函数就可以达到同样的效果,而不会增加JavaScript本身的复杂性。
注意:这与此问题有关,但我在这里询问的是“为什么”,而不是“如何”。我试图理解动机。

2
wrapToReturnPromise 很复杂(而且经常被错误地实现/过于天真),并且比必要的开销更大。使用 awaitasync function 可以更好地被引擎理解和优化。 - Bergi
3
真正的威力来自于同时拥有异步生成器函数和生成器语法是无法达到这一点的。需要注意的是,仅使用生成器语法是不够的。 - Bergi
2
"async/await" 不是 ES7(ES2016)的一部分!它将成为今年发布的 ES2017 的一部分。 - Felix Kling
1个回答

8

乍一看,语法相似,您可能会认为代码的行为也类似--但实际上存在一些关键差异:

  • 表达清晰: function*yieldasync functionawait 的含义有很大的不同,类似于 Subclass.prototype = Object.create(Superclass.prototype); Subclass.prototype.constructor = Subclassclass Subclass extends Superclass 的不同。

  • 运算符优先级: 你可以使用 await a + await b 表示 (await a) + (await b),但是 yield a + yield b 表示 yield (a + (yield b))

  • 未来发展: async/await 为乐观事务锁定和推测执行等一些非常有趣的工作铺平了道路,因为它们(如本线程中所述)是原子性边界的显式标记。

  • 其他论点: 对于 async/await 还有许多反对意见 -- 包括许多人认为生成器更好,并且认为 async/await 正在朝着错误的方向发展。

< p > < em > 这段内容是从ES讨论网站中无耻地摘录的。我鼓励你阅读整个帖子,因为它有关于这个主题的一些非常有趣的讨论。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接