我刚读这篇精彩的文章 -
https://www.promisejs.org/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/await
实现async关键字的方式。所以问题是,如果是这样的话,那么await
关键字和yield
关键字之间的区别是什么呢? await
总是将某些东西变成一个承诺,而yield
没有做出这样的保证吗?这是我最好的猜测!
你还可以看到async / await与本文中的生成器的yield相似,他描述了'spawn'函数:https://jakearchibald.com/2014/es7-async-functions/
yield
可以被认为是await
的基石。 yield
获取它给出的值并将其传递给调用者。然后呼叫者可以用该值做任何他想做的事情(1)。之后,调用者可以将值返回给生成器(通过generator.next()
),这将成为yield
表达式(2)的结果,或者是由yield
表达式(3)引发的错误。
async
-await
可以考虑使用yield
。在(1)调用者(即async
-await
驱动程序 - 与您发布的函数类似)将使用与new Promise(r => r(value)
类似的算法将值包装在一个承诺中(注意,不是Promise.resolve
,但这不是什么大问题)。然后它等待承诺解决。如果它满足,则将完成的值传递回(2)。如果它拒绝,它会将拒绝原因作为错误抛出(3)。
所以async
-await
的效用就是这种机制,它使用yield
将产生的值展开为一个承诺并将其解析后的值传回,重复直到函数返回其最终值。
嗯,事实证明,async / await和generator之间存在非常密切的关系。我相信async / await将永远建立在生成器上。如果你看看Babel变异async / await的方式:
巴贝尔认为:
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);
});
把它变成这个
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);
}));
你做数学。
这使得async关键字看起来就像包装函数一样,但是如果是这种情况那么await就会变成yield,那么稍后当它们变成本机时可能还会有更多的东西。
你可以在这里看到更多的解释:https://www.promisejs.org/generators/
什么是
await
关键字和yield
关键字之间的区别?
await
关键字仅用于async function
s,而yield
关键字仅用于生成器function*
s。那些明显不同 - 一个返回承诺,另一个返回生成器。
await
总是将某些东西变成一个承诺,而yield
没有做出这样的保证吗?
是的,await
将把Promise.resolve
称为期待值。
yield
只是产生发电机外的值。
使用Async / Await 99%的时间比生成器。为什么?
试试这个测试程序,我曾经用它来理解await / async和promises
程序#1:没有承诺它不会按顺序运行
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');
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');
在许多方面,生成器是async / await的超集。现在,async / await比co具有更清晰的堆栈跟踪,yield
是最流行的基于lib的async / await-like生成器。您可以使用生成器实现自己的async / await风格并添加新功能,例如对非承诺的blog post的内置支持或在RxJS observables上构建它。
因此,简而言之,生成器为您提供了更大的灵活性,基于生成器的库通常具有更多功能。但是,async / await是该语言的核心部分,它是标准化的,不会在您之下发生变化,并且您不需要库来使用它。我有一个qazxswpoi,详细介绍了async / await和generator之间的区别。