详解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的更多用法,下次再写,欢迎关注我!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。