我刚刚阅读了一篇很棒的文章« Generators »,它清楚地强调了这个函数,它是处理生成器函数的助手函数:
function async(makeGenerator){
return function () {
var generator = makeGenerator.apply(this, arguments);
function handle(result){
// result => { done: [Boolean], value: [Object] }
if (result.done) return Promise.resolve(result.value);
return Promise.resolve(result.value).then(function (res){
return handle(generator.next(res));
}, function (err){
return handle(generator.throw(err));
});
}
try {
return handle(generator.next());
} catch (ex) {
return Promise.reject(ex);
}
}
}
- 我假设
async
关键字或多或少是用async
/await
实现的。* 所以问题是,如果是这样的话,那么await
关键字和yield
关键字之间的区别是什么?await
是否总是将某些内容转换为promise,而yield
则没有这样的保证?这是我最好的猜测!
您还可以在本文中看到async
/await
如何类似于yield
的生成器,其中他描述了“spawn”函数ES7 async functions。
8条答案
按热度按时间siv3szwd1#
事实证明,
async
/await
和发电机之间有非常密切的关系。而且我相信async
/await
将永远构建在发电机上。如果你看看Babel转译async
/await
的方式:Babel对此表示:
然后把它变成这样
你自己算算
这使得它看起来像
async
关键字只是 Package 器函数,但如果是这种情况,那么await
就变成了yield
,当它们成为原生时,可能会有更多的图片。你可以在这里看到更多的解释:https://www.promisejs.org/generators/
lsmd5eda2#
yield
可以被认为是await
的构建块。yield
获取给定的值并将其传递给调用者。然后调用者可以对该值(1)做任何它希望做的事情。稍后,调用者可能会将一个值返回给生成器(通过generator.next()
),该值将成为yield
表达式(2)的结果,或者是一个似乎由yield
表达式(3)抛出的错误。async
-await
可以考虑使用yield
。在⑴处,呼叫者(即,async
-await
驱动程序-类似于您发布的函数)将使用类似于new Promise(r => r(value)
的算法将值 Package 在promise中(注意,* 不是 *Promise.resolve
,但这不是什么大问题)。然后等待promise解析。如果满足,则在(2)处将满足的值传递回。如果它拒绝,则在(3)处将拒绝原因作为错误抛出。因此
async
-await
的效用是使用yield
将产生的值作为promise展开并将其解析的值传递回去,重复直到函数返回其最终值。hc8w905p3#
await
关键字和yield
关键字有什么区别?await
关键字只能在async function
s中使用,而yield
关键字只能在generatorfunction*
s中使用。这两个函数显然也是不同的--一个返回promise,另一个返回generator。await
是否总是将某些内容转换为promise,而yield
则没有这样的保证?是的,
await
将调用Promise.resolve
等待的值。yield
只产生生成器之外的值。qxsslcnc4#
tl;dr
**使用
async
/await
99%的时间超过生成器。**为什么?async
/await
直接取代了最常见的promise链工作流,允许代码像同步一样声明,大大简化了它。1.生成器抽象了用例,在用例中,您将调用一系列相互依赖的异步操作,最终将处于“完成”状态。最简单的例子是分页遍历最终返回最后一个集合的结果,但您只会在需要时调用一个页面,而不是立即连续调用。
async
/await
实际上是构建在生成器之上的一个抽象,以使promise的工作更容易。See very in-depth Explanation of Async/Await vs. Generators
k4ymrczo5#
尝试这个测试程序,我用它来理解
await
/async
与承诺。程序#1:如果没有promise,它就不会按顺序运行
程序#2:承诺
ujv3wf0j6#
在许多方面,生成器是async/await的超集。目前async/await的堆栈跟踪比co更清晰,co是最流行的基于async/await的生成器。您可以使用生成器实现自己的异步/等待风格,并添加新功能,例如在非Promise上内置对
yield
的支持或在RxJS Observables上构建它。因此,简而言之,生成器为您提供了更大的灵活性,基于生成器的库通常具有更多的功能。但是async/await是语言的核心部分,它是标准化的,不会在你的控制下改变,你不需要一个库来使用它。我有一个blog post,详细说明了async/await和generator之间的区别。
bqujaahr7#
yield
+gen.next()
-as-a-language-feature可用于描述(或实现)await-async
抽象出的底层控制流。正如其他答案所暗示的那样,
await
-as-a-language-feature是(或者可以认为是)yield
之上的实现。这里有一个更直观的理解:
假设我们在一个异步函数
await A -> await B -> ...
中有42个awaits
实际上,它相当于拥有
yield A -> tries resolve this as a Promise
[1]-> if resolvable, we yield B, and repeat [1] for B
-> if not resolveable, we throw
因此,我们最终在生成器中得到42
yields
。在我们的控制器中,我们简单地继续执行gen.next()
,直到它完成或被拒绝。(即这与在包含42个await
的异步函数上使用await
相同。这就是为什么像redux-saga这样的lib利用generator将promise通过管道传递到saga中间件,以便在一个地方解析所有promise;从而将Promises构造与它们的求值分离,从而与Free Monad共享密切的相似性。
dnph8jn48#
其思想是递归地链接
then()
调用以复制await
的行为,从而允许以同步方式调用async
例程。生成器函数用于将控制权(和每个值)从被调用方返回给调用方,它恰好是_asyncToGenerator()
Package 器函数。如上所述,这是Babel用来创建polyfill的技巧。我稍微编辑了代码,使其更具可读性,并添加了注解。