通常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 --save
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();
})
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。