es6提供的生成器generator生成的是迭代器。(function * fn(){yield xxx})
function sum(){
let r = [...arguments].join('');
console.log(r)
}
let obj = {0:1,1:2,2:3,length:3}
console.log([...obj])
上述代码第一个是可以使用es6的扩展运算符...来展开的,而obj则不可以,因为默认的obj是不能被迭代的。那么如果想要可以迭代,需要自己实现下面的代码。
// 自己实现迭代器需要注意以下几点
/*
1、需要增加一个[Symbol.iterator]属性
2、返回一个对象包含next属性,属性值为一个函数
3、next函数返回一个对象,对象包括value和done属性,当done为false的时候表示未迭代完成,为true的时候表示迭代完成
*/
let o = {0:1,1:2,2:3,length:3,[Symbol.iterator]:function(){
let currentIndex = 0;
let that = this;
return {
next(){
return {value[currentIndex++],done:currentIndex-1 === that.length}
}
}
}}
// 使用生成器产生迭代器
let o = {0:1,1:2,2:3,length:3,[Symbol.iterator]:function *(){
let index = 0;
while(index!==this.length){
yield this[index];
index++;
}
}
生成器函数执行完返回一个迭代器
function * say(){
yield 'node'
yield 'react'
yield 'vue'
}
let it = say();
let flag = false;
do{
let {value,done} = it.next()
flag = done
}while(!flag)
yield的返回值(next第一次传值是无意义的,以后的每次传值都是n-1次yield的返回值,例如next第二次传递200的时候,a的值为200)
function * say(){
let a = yield 'hello'
console.log(a)
let b = yield 'world'
console.log(b)
let c = yield 'xxx'
console.log(c)
}
let it = say();
it.next(100);
it.next(200);
it.next(300);
co+generator实现后一项依赖前一项的异步请求
let fs = require('fs');
function read(){
return new Promise(function(resolve,reject){
fs.readFile(file,'utf8',function(err,data){
if(err) reject(err)
resolve(data)
})
})
}
function * r(){
let r1 = yield read('./1.txt');
let r2 = yield read(r1);
let r3 = yield read(r2);
return r3
}
function co(it){
return new Promise(function(resolve,reject){
//使用迭代器实现 异步操作按顺序执行。
function next(data){
let {value,done} = it.next(data);
if(done){
resolve(value)
}else{
value.then(function(data){
next(data)
},reject)
}
}
next()
})
}
co(r()).then(function(data){
console.log(data)
})
两个工具函数promisify和promisifyAll
function promisify(fn){
return function(...args){
return new Promise(function(resolve,reject){
fn(...args,function(err,data){
if(err) reject(err)
resolve(data)
})
})
}
}
function promisifyAll(obj){
for(let key in obj){
let fn = obj[key];
if(typeof fn === 'function'){
obj[key] = promisify(fn)
}
}
}