一般ajax请求都会用到异步调用问题,为了保证调用顺序的正确性,通常会用到callback,后来出现了promise的解决方案。
在异步编程中,还有一种解决方案,那就是generator生成器函数,这个函数会返回一个迭代器。ajax
特色:函数声明只是多了个*号来表示这是一个生成器函数,而且通常能够在函数内看到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)
具体的执行步骤,见图分解npm
产出的值 是一个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 --savepromise
let 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(); }) }