详解ES6中的三种异步解决方案
前置知识准备
- Generator函数执行会返回一个迭代器(Iterator),在迭代器上可以调用 next()方法,执行下一个yield 或return
- 调用 next()方法,会返回一个对象{value:res,done:false},value的值为yield之后表达式的值,done的值表示迭代器,是否已经执行完毕(最后一个yield 或return)
- next()方法,可以传入一个值,做为前一个yield表达式的返回值
有了这些知识,可以把Promise对象做一个的yield的值,配合一个执行器,来处理异步操作
方式一:Generator+Promise+执行器
constfs=require('fs')
//Promise版的readFile
constreadFile=function(fileName){
returnnewPromise(function(resolve,reject){
fs.readFile(fileName,function(err,data){
if(err)returnreject(error);
resolve(data);
})
})
}
constgen=function*(){
letf1=yieldreadFile('a.txt');
letf2=yieldreadFile('b.txt');
console.log('F1--->',f1.toString());
console.log('F2--->',f2.toString());
}
//基于Generator和Promise的自动执行器
functionrun(gen){
letg=gen();
functionnext(data){
letresult=g.next(data);
if(result.done)returnresult.value;
result.value.then(function(data){
next(data);
});
}
next();
}
run(gen);
执行器中的result.value现在是一个Promise,通过then方法拿到需要的结果,传下一次next方法,这样letf1=yieldreadFile('a.txt'); 就可以拿到值!
方式二:Generator+Thunk函数+执行器
constfs=require('fs')
//把一个单一执行的函数,变成需要再次调用的函数,固定一部分参数
functionthunkify(fn,obj={}){
returnfunction(){
letargs=Array.from(arguments);
returnfunction(m){
args.push(m)
returnfn.apply(obj,args)
}
}
}
constreadFile=thunkify(fs.readFile,fs);
constgen=function*(){
letf1=yieldreadFile('a.txt');
letf2=yieldreadFile('b.txt');
console.log('F1-->',f1.toString());
console.log('F2-->',f2.toString());
}
//基于Generator和Thunk函数的自动执行器
functionrun(fn){
letgen=fn();
functionnext(err,data){
letresult=gen.next(data);
if(result.done)return1;
result.value(next);
}
next();
}
run(gen);
这里的Thunk转换器,把原来的fs.readFile函数转换成需要两次调用的函数,readFile的执行结果,可以通过回调函数能参数传递出来,再传给next方法
方式三:基于async函数和await的异步处理方式
constfs=require('fs')
//Promise版的readFile
constreadFile=function(fileName){
returnnewPromise(function(resolve,reject){
fs.readFile(fileName,function(err,data){
if(err)returnreject(err);
resolve(data);
})
})
}
constasyncReadFile=asyncfunction(){
constf1=awaitreadFile('a.txt');
constf2=awaitreadFile('b.txt');
console.log(f1.toString());
console.log(f2.toString());
};
asyncReadFile();
readFile函数对比方式一没有大的变化,Generator函数变成了async函数,可见这处方式只是方式一的一个语法糖,async函数自带了执行器!
这个话题,还可以衍生出yield的更多用法,下次再写,欢迎关注我!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。