一.Iterator
(1).实现原理
function makeIterator(arr){
var iterRatorIndex = 0;
return{
next(){
return arr.length > iterRatorIndex ?
{value:arr[iterRatorIndex++],done:false}:
{value:undefined,done:true}
}
}
}
var test = makeIterator(['a','b']);
console.log(test.next());//{value: "a", done: false}
(2).内外部迭代器
(3).迭代器迭代对象
let obj = {
start:[1,3,2],
end:[7,8,9],
[Symbol.iterator](){
let arr = [...this.start,...this.end];
let iterRatorIndex = 0;
return{
next(){
return arr.length > iterRatorIndex ?
{value:arr[iterRatorIndex++],done:false}:
{value:undefined,done:true}
}
}
}
}
for(let a of obj){
console.log(a);
}// 1 3 2 7 8 9
let obj = {
a:1,
b:2,
[Symbol.iterator]() {
let map = new Map();
for (let [key, value] of Object.entries(obj)) {
map.set(key, value);
}
let mapArr = [...map.entries()];
let iterRatorIndex = 0;
return {
next() {
return mapArr.length > iterRatorIndex ?
{ value: mapArr[iterRatorIndex++],done:false}:
{value:undefined,done:true}
}
}
}
}
for(let a of obj){
console.log(a);
}
//(2) ["a", 1]
["b", 2]
抽取
var a = obj[Symbol.iterator]();
console.log(a.next());
{value: Array(2), done: false}
用for(let [key,value] of Object.entries(obj))也能解决这个问题,但是不能实现抽取
(4).return
let obj = {
a:1,
b:2,
[Symbol.iterator]() {
let map = new Map();
for (let [key, value] of Object.entries(obj)) {
map.set(key, value);
}
let mapArr = [...map.entries()];
let iterRatorIndex = 0;
return {
next() {
return mapArr.length > iterRatorIndex ?
{ value: mapArr[iterRatorIndex++],done:false}:
{value:undefined,done:true}
},
return() {
console.log('触发了错误');
}
}
}
}
for(var c of obj){
console.log(c);
throw new Error('错误')
}
["a", 1]
触发了错误
Uncaught Error: 错误
二.generator
(1).基本形式
function * test(){}
let iter = test();
console.log(iter);
(2).yield
function * test(){
console.log(1);
yield 'a';
console.log(2);
yield 'b';
console.log(3);
let a = yield '5'
console.log(a);
return 'd';
yield 'c';
}
let iter = test();
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
1
{value: "a", done: false}
2
{value: "b", done: false}
3
undefined
{value: "d", done: true}
{value: undefined, done: true}
{value: undefined, done: true}
- 与抽取的方式相同,会有产出值(迭代器对象)
- yield相当于一个区块,每一个区块的代码内容则为yield上方的代码,如果不next则不执行区块代码
- return后 之后所有的yield的产出值均为undefined
- 生成函数和yield和异步函数结合,就可以理解为状态机
- 也可以理解为生成迭代器函数
- yield本身是不返回值的,只能在外部通过next抽取函数获取,内部是un
function * test(){
console.log('hello'+(yield 123));
}
let iter = test();
console.log(iter.next());
{value: 123, done: false}
function * test(){
foo(yield 'a',yield 'c')
}
function foo(a,b){
console.log(a,b);
}
let iter = test();
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
{value: "a", done: false}
{value: "c", done: false}
undefined undefined
{value: undefined, done: true}
function * test(){
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}
for(let i of test()){
console.log(i);
}
//1 2 3 4 5
function * test(){
let value1 = yield 1;
console.log('value1'+value1);
let value2 = yield 2;
console.log('value2'+value2);
let value3 = yield 3;
console.log('value3'+value3);
let value4 = yield 4;
console.log('value4'+value4);
}
let iter = test();
console.log(iter.next('none'));
console.log(iter.next('two'));
console.log(iter.next('three'));
{value: 1, done: false}
value1two
{value: 2, done: false}
value2three
{value: 3, done: false}
因为yield得产出值就为迭代函数,所以可以直接用yield去替代以前next的写法
let obj = {
start:[1,2,3],
end:[4,5,6],
[Symbol.iterator] : function*(){
var itemIndx = [...this.start,...this.end],
length = itemIndx.length,
idxof = 0;
while(length>idxof){
yield itemIndx[idxof++]
}
}
}
for(var c of obj){
console.log(c);
}
console.log(obj[Symbol.iterator]().next());
// 1 2 3 4 5 6 {value: 1, done: false}
(3).generator状态机
let fs = require('fs')
function promisify(fn){
return function(...args){
return new Promise((resolve,reject)=>{
fn(...args,(err,data)=>{
if(data){
resolve(data)
}else{
reject(err)
}
})
})
}
}
let readFile = promisify(fs.readFile)
function * read(){
let value1 = yield readFile('./name.txt','utf-8');
let value2 = yield readFile(value1,'utf-8');
let value3 = yield readFile(value2,'utf-8');
console.log(value3);
}
let iter = read();
let {value,done} = iter.next();
value.then((val)=>{
let{value,done} = iter.next(val)
value.then((val2)=>{
let{value,done} = iter.next(val2)
value.then((value)=>{
console.log(value);
})
})
})
输出最后一个文件中的值99
- 首先通过Promisify把异步函数promise化
- 再通过生成函数 调用每一个异步函数 这样就可以通过next()调取下一个异步函数,并将上一个的异步函数结果通过next函数传参了,且返回Promise对象这样就可以通过then监听到了
因为每次获得结果都要通过上面的嵌套next()获得,特别麻烦,所以生成了CO
function Co(iter){
return new Promise((resolve,reject)=>{
let next = (data) =>{
let {value,done} = iter.next(data);
if(done){
resolve(value)
}else{
value.then((val)=>{
next(val);
})
}
}
next();
})
}
let promise = Co(read())
promise.then((val)=>{
console.log(val);
})
结果与上方next then嵌套结果一致