Javascript async/await 和 ES6 生成器之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36196608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between async/await and ES6 yield with generators
提问by Alexander Mills
I was just reading this fantastic article ?Generators? and it clearly highlights this function, which is a helper function for handling generator functions:
我只是在读这篇精彩的文章?发电机?它清楚地突出显示了这个函数,它是一个处理生成器函数的辅助函数:
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);
}
}
}
which I hypothesize is more or less the way the async
keyword is implemented with async
/await
.So the question is, if that is the case, then what the heck is the difference between the await
keyword and the yield
keyword? Does await
always turn something into a promise, whereas yield
makes no such guarantee? That is my best guess!
我假设这或多或少是async
关键字实现的方式async
/ await
。所以问题是,如果是这样,那么await
关键字和yield
关键字之间到底有什么区别?是否await
总是将某些东西变成承诺,而yield
没有做出这样的保证?这是我最好的猜测!
You can also see how async
/await
is similar to yield
with generators in this article where he describes the 'spawn' function ES7 async functions.
您还可以在本文中看到async
/与生成器的await
相似之处yield
,他描述了“生成”函数ES7 异步函数。
采纳答案by Alexander Mills
Well, it turns out that there is a very close relationship between async
/await
and generators. And I believe async
/await
will always be built on generators. If you look at the way Babel transpiles async
/await
:
好吧,事实证明async
/await
和生成器之间有非常密切的关系。我相信async
/await
将始终建立在生成器上。如果你看看 Babel 转译async
/的方式await
:
Babel takes this:
巴贝尔采取了这个:
this.it('is a test', async function () {
const foo = await 3;
const bar = await new Promise(resolve => resolve('7'));
const baz = bar * foo;
console.log(baz);
});
and turns it into this
并把它变成这个
function _asyncToGenerator(fn) {
return function () {
var gen = fn.apply(this, arguments);
return new Promise(function (resolve, reject) {
function step(key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(function (value) {
return step("next", value);
}, function (err) {
return step("throw", err);
});
}
}
return step("next");
});
};
}
this.it('is a test', _asyncToGenerator(function* () { // << now it's a generator
const foo = yield 3; // <<< now it's yield, not await
const bar = yield new Promise(resolve => resolve(7));
const baz = bar * foo;
console.log(baz);
}));
you do the math.
你做数学。
This makes it look like the async
keyword is just that wrapper function, but if that's the case then await
just gets turned into yield
, there will probably be a bit more to the picture later on when they become native.
这使得async
关键字看起来只是那个包装函数,但如果是这种情况,那么它await
只是变成了yield
,当它们成为本机时,可能会有更多的图片。
You can see more of an explanation for this here: https://www.promisejs.org/generators/
你可以在这里看到更多的解释:https: //www.promisejs.org/generators/
回答by Arnavion
yield
can be considered to be the building block of await
. yield
takes the value it's given and passes it to the caller. The caller can then do whatever it wishes with that value (1). Later the caller may give a value back to the generator (via generator.next()
) which becomes the result of the yield
expression (2), or an error that will appear to be thrown by the yield
expression (3).
yield
可以被认为是await
. yield
获取它给定的值并将其传递给调用者。然后调用者可以使用该值 (1) 做任何想做的事情。稍后,调用者可能会将一个值返回给生成器(通过generator.next()
),该值将成为yield
表达式 (2)的结果,或者yield
表达式 (3)会抛出一个错误。
async
-await
can be considered to use yield
. At (1) the caller (i.e. the async
-await
driver - similar to the function you posted) will wrap the value in a promise using a similar algorithm to new Promise(r => r(value)
(note, notPromise.resolve
, but that's not a big deal). It then waits for the promise to resolve. If it fulfills, it passes the fulfilled value back at (2). If it rejects, it throws the rejection reason as an error at (3).
async
-await
可以考虑使用yield
。在 (1) 调用者(即async
-await
驱动程序 - 类似于您发布的函数)将使用类似于new Promise(r => r(value)
(注意,不是Promise.resolve
,但这不是什么大问题)的算法将值包装在承诺中。然后它等待承诺解决。如果满足,则将满足的值传回 (2)。如果它拒绝,则在 (3) 处将拒绝原因作为错误抛出。
So the utility of async
-await
is this machinery that uses yield
to unwrap the yielded value as a promise and pass its resolved value back, repeating until the function returns its final value.
所以效用async
-await
是这款机器使用yield
解开了产生价值的承诺,并通过其解析值回,重复,直到函数返回其最终值。
回答by Bergi
what the heck is the difference between the
await
keyword and theyield
keyword?
await
关键字和yield
关键字之间到底有什么区别?
The await
keyword is only to be used in async function
s, while the yield
keyword is only to be used in generator function*
s. And those are obviously different as well - the one returns promises, the other returns generators.
的await
关键字仅在使用async function
S,而yield
关键字是唯一的在发电机使用function*
秒。这些显然也不同——一个返回承诺,另一个返回生成器。
Does
await
always turn something into a promise, whereasyield
makes no such guarantee?
是否
await
总是将某些东西变成承诺,而yield
没有做出这样的保证?
Yes, await
will call Promise.resolve
on the awaited value.
是的,await
将调用Promise.resolve
等待的值。
yield
just yields the value outside of the generator.
yield
只产生生成器之外的值。
回答by Jason Sebring
tl;dr
tl;博士
Use async
/await
99% of the time over generators.Why?
在发电机上使用async
/ await
99% 的时间。为什么?
async
/await
directly replaces the most common workflow of promise chains allowing code to be declared as if it was synchronous, dramatically simplifying it.Generators abstract the use case where you would call a series of async-operations that depend on each other and eventually will be in a "done" state. The most simple example would be paging through results that eventually return the last set but you would only call a page as needed, not immediately in succession.
async
/await
is actually an abstraction built on top of generators to make working with promises easier.
async
/await
直接替换了最常见的承诺链工作流,允许将代码声明为同步,从而大大简化了它。生成器抽象了用例,您将调用一系列相互依赖的异步操作,最终将处于“完成”状态。最简单的例子是对最终返回最后一组的结果进行分页,但您只会根据需要调用一个页面,而不是立即连续调用。
async
/await
实际上是一个建立在生成器之上的抽象,使使用 promise 更容易。
回答by Kamal Kumar
Try this test programs which I used to understand await
/async
with promises.
试试这个我曾经理解await
/async
承诺的测试程序。
Program #1: without promises it doesn't run in sequence
程序#1:没有promise,它不会按顺序运行
function functionA() {
console.log('functionA called');
setTimeout(function() {
console.log('functionA timeout called');
return 10;
}, 15000);
}
function functionB(valueA) {
console.log('functionB called');
setTimeout(function() {
console.log('functionB timeout called = ' + valueA);
return 20 + valueA;
}, 10000);
}
function functionC(valueA, valueB) {
console.log('functionC called');
setTimeout(function() {
console.log('functionC timeout called = ' + valueA);
return valueA + valueB;
}, 10000);
}
async function executeAsyncTask() {
const valueA = await functionA();
const valueB = await functionB(valueA);
return functionC(valueA, valueB);
}
console.log('program started');
executeAsyncTask().then(function(response) {
console.log('response called = ' + response);
});
console.log('program ended');
Program #2: with promises
程序#2:使用承诺
function functionA() {
return new Promise((resolve, reject) => {
console.log('functionA called');
setTimeout(function() {
console.log('functionA timeout called');
// return 10;
return resolve(10);
}, 15000);
});
}
function functionB(valueA) {
return new Promise((resolve, reject) => {
console.log('functionB called');
setTimeout(function() {
console.log('functionB timeout called = ' + valueA);
return resolve(20 + valueA);
}, 10000);
});
}
function functionC(valueA, valueB) {
return new Promise((resolve, reject) => {
console.log('functionC called');
setTimeout(function() {
console.log('functionC timeout called = ' + valueA);
return resolve(valueA + valueB);
}, 10000);
});
}
async function executeAsyncTask() {
const valueA = await functionA();
const valueB = await functionB(valueA);
return functionC(valueA, valueB);
}
console.log('program started');
executeAsyncTask().then(function(response) {
console.log('response called = ' + response);
});
console.log('program ended');
回答by vkarpov15
In many ways, generators are a superset of async/await. Right now async/await has cleaner stack traces than co, the most popular async/await-like generator based lib. You can implement your own flavor of async/await using generators and add new features, like built-in support for yield
on non-promises or building it on RxJS observables.
在许多方面,生成器是 async/await 的超集。现在 async/await 比co具有更清晰的堆栈跟踪,co是最流行的基于 async/await 的生成器库。您可以使用生成器实现自己的 async/await 风格并添加新功能,例如yield
对非承诺的内置支持或在 RxJS observables 上构建它。
So, in short, generators give you more flexibility and generator-based libs generally have more features. But async/await is a core part of the language, it's standardized and won't change under you, and you don't need a library to use it. I have a blog postwith more details on the difference between async/await and generators.
因此,简而言之,生成器为您提供了更大的灵活性,基于生成器的库通常具有更多功能。但是 async/await 是该语言的核心部分,它是标准化的并且不会在您的领导下发生变化,并且您不需要库来使用它。我有一篇博客文章,其中详细介绍了 async/await 和生成器之间的区别。