reference:
- https://www.cnblogs.com/chenjinxinlove/p/8467774.html
- https://juejin.im/post/5b54ca8ef265da0f7e628b6f
- https://juejin.im/post/5a30193051882503dc53af3c#heading-13
- https://juejin.im/post/5bcf3e3f6fb9a05cd53b3e3d#heading-11
1. 深入理解异步操作
在“认识generator”这篇文章中,我更多地是从迭代器的角度去看generator
,我们现在从异步操作的角度来看待generator
:
function* gererator(){
//do some stuff
yield value1;
//do some stuff;
yield value2;
}
执行权一直calling code
和generator
函数两个地方轮换,两段代码的数据交流可以通过yield
和.next(data)
进行交换。
generator
异步读取文件的实例:
var fs=require('fs');
var readfile=function(filename){
return new Promise((resolve,reject=>{
fs.readFile(filename, (error,data)=>{
if(error) reject(new Error('whoops');
resolve(data);
});
});
}
//generator
var gen=function* (){
var file1=yield readfile('./data1.json');
var file2= yield readfile('./data2.json');
console.log('done');
}
//calling code
var generator=gen();
generator.next().value.then(data=>{
generator.next(data).value.then((data)=>{
generator.next(data);
}
);
});
在外层的calling code部分,我们可以用自动执行器,来让generator
函数执行,比如我们可以引入模块co
来完成上述calling code的操作。
也可以自己写一个自动执行器:
function run(generator){
var g=generator();
function next(data){
var result=g.next(data);
if(result.done){
console.log(result.value);
}else{
result.value.then(function(data){
next(data);
});
}
}
next();
}
事实上,上述代码如果async
和await
的语法来写,就会变得非常简洁。
async function loadFile(){
var file1=await readfile('./data1.json');
var file2=await readfile('/data2.json');
console.log('done');
}
2. async
函数的实现原理, 就是将Generator 函数和自动执行器, 包装在一个函数里。
function getName(name){
return new Promise((resolve)=>{
setTimeout(resolve(name),1000);
});
}
function* gen(){
let data1=yield getName('nancy');
let data2=yield getName('bill');
return [data1,data2];
}
function run(generator){
return new Promise(resolve=>{
var g=generator();
var output;
function next(data){
var result=g.next(data);
if(result.done){
output=result.value;
resolve(output);
}else{
result.value.then(function(data){
next(data);
});
}
}
next();
});
}
run(gen).then(console.log); //output ['nancy','bill'].
//example:
// var fs=require('fs');
function getName(name)
{
return new Promise(resolve=>{
setTimeout(resolve(name),1000);
});
}
async function readfile(name1,name2){
let data1=await getName(`hello, ${name1}`);
let data2=await getName(`hello, ${name2}`);
return [data1,data2];
}
// now use promise and generator.
function* generator(name1,name2){
let data1=yield getName(`hello, ${name1}`);
let data2=yield getName(`hello, ${name2}`);
return [data1,data2];
}
function wrapper(gen){
return function(...args){
return new Promise(resolve=>{
var g=gen(...args);
function next(data){
var result=g.next(data);
if(result.done) resolve(result.value)
else{
result.value.then(data=>{
next(data);
});
}
}
next();
});
}
}
var readfile_gen=wrapper(generator);
readfile('jason','gisele').then(console.log);
readfile_gen('jason','gisele').then(console.log);
包装函数:
const wrapAsync=function(generatorFn){
return function(...args){
return new Promise(resolve=>{
var g=generatorFn(...args);
function next(data){
var result=g.next(data);
if(result.done) resolve(result.value);
else{
result.value.then(data=>{
next(data);
});
}
}
next();
});
}
}