- generator(生成器),由es6提供的,生成的是迭代器;
- 进阶的语法:async + await;
- dva + react 中有redux-saga,redux-saga根据generator写出来的;
- generator 可以配合promise使用,也可以不配合使用
- 生成器是用来生成迭代器的;
generotor.1.js
let likeArray = { 0: 1, 1: 2, 2: 3, length: 3 };
let arr = [...likeArray];
console.log(arr); // 报错:likeArray is not iterable
generotor.2.js
// 函数对象内置:Sync
function arg() {
console.log([...arguments]); // 打印:[ 1, 2, 3, 4 ]
}
arg(1, 2, 3, 4);
generotor.3.js
- 迭代器就是一个有next方法的对象,每次调用next都会返回一个对象,对象里有done,value;for of必须拥有迭代器的方法才能调用;
// 对象添加迭代器
let likeArray = {
0: 1, 1: 2, 2: 3, length: 3, [Symbol.iterator]() {
let flag = false; // 默认迭代未完成
let index = 0; // 当前对象的索引
let that = this; // 当前对象
return {
next() {
return { done: index === that.length, value: that[index++] }; // done为true表示迭代完成,为false迭代未完成会一值迭代
}
}
}
};
// 迭代器就是一个有next方法的对象,每次调用next都会返回一个对象,对象里有done,value;for of必须拥有迭代器的方法才能调用;
let arr = [...likeArray];
console.log(arr); // 打印:[ 1, 2, 3 ]
generotor.4.js
- 生成器可以实现生成迭代器,生成器函数就是再函数关键字中加个
*配合yield来使用
let likeArray = {
0: 1, 1: 2, 2: 3, length: 3, [Symbol.iterator]: function* () {
let index = 0;
yield this[index++];
yield this[index++];
}
};
let arr = [...likeArray];
console.log(arr); // 打印:[ 1, 2]
generator.5.js
- yield方法原理:执行next方法时,每次遇到yield方法会停止执行函数,并返回yield后的值;
- yield函数
function * gen(){
yield 1;
yield 2;
}
let it = gen();
let r = it.next();
console.log(r);
r = it.next();
console.log(r);
r = it.next();
console.log(r);
/*
打印:
{ value: 1, done: false }
{ value: 2, done: false }
{ value: undefined, done: true }
*/
generator.6.js
- generator的好处就是遇到yield就会暂停,调用next会继续往下执行
- generator原理
function * gen(){
yield 1;
yield 2;
}
let it = gen();
let flag = false;
do{
let {value,done} = it.next();
flag = done;
console.log(value); // 打印: 1 2 undefined
}while(!flag);
generator.7.js
let likeArray = {
0: 1, 1: 2, 2: 3, length: 3, [Symbol.iterator]: function* () {
let index = 0;
while (index !== this.length) {
yield this[index++];
}
}
};
let arr = [...likeArray];
console.log(arr); // 打印:[ 1, 2, 3 ]
generator.8.js
- generator next参数使用原理:第一次传参无意义;第二次及以上传参,参数会返回给上次yield的返回值;
function* say() {
let a, b, c;
a = yield 'hello';
console.log('a', a);
b = yield 'world';
console.log('b', b);
c = yield 'Kong';
console.log('c', c);
}
let it = say();
it.next(100); // 第一次next传递参数是无意义的
it.next(200); // 第二次next执行时传递的参数会返回给第一次yield的返回值;
it.next(300);
it.next(400);
/*
打印:
a 200
b 300
c 400
*/
generator.9.js
let fs = require('fs');
function read(file) {
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('name.txt');
let r2 = yield read(r1);
let r3 = yield read(r2);
return r3;
}
let it = r();
let { value, done } = it.next();
// generator方法
value.then(function (data) { // data -> age.txt
let { value, done } = it.next(data);
value.then(function (data) { // data -> address.txt
let { value, done } = it.next(data);
value.then(function (data) { // data -> 结果
console.log(data);
})
})
})
// promise方法
read('name.txt', function (err, data) {
return read(data);
}).then(function (data) {
return read(data);
}).then(function (data) {
return read(data);
}).then(function (data) {
console.log(data);
})
generator.10.js
- generator+co完整版
- 可以引用co库
cnpm i co
- 自定义co函数
let fs = require('fs');
function read(file) {
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('pracetice/name.txt');
let r2 = yield read(r1);
let r3 = yield read(r2);
return r3;
}
function co(it) {
return new Promise(function (resolve, reject) {
// next方法 express koa 原理都是这样的
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);
})