通常ajax请求都会用到异步调用问题,为了保证调用顺序的正确性,一般会用到callback,后来出现了promise的解决方案。
在异步编程中,还有一种解决方案,那就是generator生成器函数,这个函数会返回一个迭代器。特点:函数声明只是多了个*号来表示这是一个生成器函数,并且一般可以在函数内看到yield关键字。 原理:它会将一个函数分为若干个小函数,并且返回一个迭代器,通过调用迭代的next方法(移动指针),内部遍历值、状态,保持正确的执行顺序。每次调用next方法,都会向下执行一步。 用法: 1.先产出,下一个next负责传值,然后接收新值。 2.yield后面跟着的是value值(产出值)。 yield等号前面的 是我们当前调用next传进来的 值。没有等号代表不接收新值。 注意点:迭代器的第一个next执行,传值是无效的。
function *read(){ console.log(1); var content1 = yield 'qs'; console.log(content1); var content2 = yield '9';![图片描述][1] console.log(content2); return content2;}var it = read();var a = it.next() //输出 1 a:{value:'qs',done:false}var b = it.next('hello')//输出hello b:{value:'9',done:false}var c = it.next('generator')//输出generator c:{value:'generator',done:true}var d = it.next('123')//输出generator c:{value:undefined,done:true}console.log(a,b,c,d)
具体的执行步骤,见图分解
产出的值 是一个object,包含两个key :value 和 done value 表示产出的值,done表示执行状态(迭代器是否执行完成,全部遍历一遍) 当done 为true时表示遍历完成。之后再次执行next,就没有产出了,所以value为undefined,done仍旧是true;
用处:generator一般和promise结合一起用
let fs = require('fs');let blueBird = require('bluebird');let read2 = blueBird.promisify(fs.readFile);function *r(){ let content1 = yield read2('./1.txt','utf8'); let content2 = yield read2(content1,'utf8'); return content2}let it2 = r();it2.next().value.then(res=>{ it2.next(res).value.then(res=>{ console.log(res); console.log(it2.next(res));//需要给content2赋值,然后产出{ value: '大大大', done: true } })});
为了更好的结合promise使用,出现了co库。
co库的作用就是:把一个生成器函数的迭代器,最后一步执行完毕后,然后统一执行一个成功回调安装:npm install co --savelet co = require('co');function *r2(){ let content1 = yield read2('./1.txt','utf8'); let content2 = yield read2(content1,'utf8'); return content2}co(r2).then(function(res){console.log(res,11111111111111)});
co库实现原理,就是利用产出值的done的状态,去判断是否需要再次递归执行next方法。
function co(it){ return new Promise(function(resolve,reject){ function next(data){ let {value,done}= it.next(data); if(!done){ value.then(res=>{ next(res); },reject) }else{ resolve(value) } } next(); })}