Ale*_*lls 69 javascript generator node.js ecmascript-6 ecmascript-next
我刚读这篇精彩的文章 -
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我假设或多或少是async关键字的实现方式async
.所以问题是,如果是这种情况,那么async
关键字和await
关键字之间的区别是什么呢?是否await
总是把东西放到一个承诺,而yield
没有这样的保证?这是我最好的猜测!
你还可以看到async/await与本文中的生成器的yield相似,他描述了'spawn'函数:https://jakearchibald.com/2014/es7-async-functions/
Arn*_*ion 38
yield
可以被认为是await
.yield
获取它给出的值并将其传递给调用者.然后呼叫者可以用该值做任何他想做的事情(1).稍后调用者可以将值返回给生成器(via generator.next()
),这将成为yield
表达式(2)的结果,或者yield
表达式(3)将出现的错误.
async
- await
可以考虑使用yield
.在(1)调用者(即async
- await
驱动程序 - 类似于你发布的函数)将使用类似的算法将值包装在一个promise中new Promise(r => r(value)
(注意,不是 Promise.resolve
,但这不是什么大问题).然后它等待承诺解决.如果它满足,则将完成的值传递回(2).如果它拒绝,它会将拒绝原因作为错误抛出(3).
所以效用async
- await
是这款机器使用yield
解开了产生价值的承诺,并通过其解析值回,重复,直到函数返回其最终值.
Ale*_*lls 35
嗯,事实证明,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);
});
Run Code Online (Sandbox Code Playgroud)
把它变成这个
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);
}));
Run Code Online (Sandbox Code Playgroud)
你做数学.
这使得async关键字看起来就像包装函数一样,但是如果是这种情况那么await就会变成yield,那么稍后当它们变成本机时可能还会有更多的东西.
Ber*_*rgi 26
await
关键字和yield
关键字之间的区别是什么?
的await
关键字仅在使用async function
S,而yield
关键字是唯一的在发电机使用function*
秒.那些明显不同 - 一个返回承诺,另一个返回生成器.
是否
await
总是把东西放到一个承诺,而yield
没有这样的保证?
是的,await
会打电话Promise.resolve
给等待的价值.
yield
只是产生发电机外的值.
在发电机上使用async
/ await
99%的时间。为什么?
async
/ await
直接替换了最常见的承诺链工作流,从而允许将代码声明为同步的,从而大大简化了代码。
生成器将用例抽象化,您将调用一系列彼此依赖的异步操作,最终将处于“完成”状态。最简单的示例是分页显示最终返回最后一组结果的结果,但是您只会根据需要调用页面,而不会立即连续调用。
async
/ await
实际上是建立在生成器之上的抽象,以使兑现承诺更加容易。
试试这个我曾经理解await
/async
承诺的测试程序。
程序#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');
Run Code Online (Sandbox Code Playgroud)
程序#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');
Run Code Online (Sandbox Code Playgroud)