生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
生成器函数声明与调用
function* gen() {
console.log('hello');
}
let iterator = gen();
console.log(iterator);//不会输出hello 是一个迭代器对象 需要调用next方法才会输出
iterator.next();
输出结果:
yield
yield相当于函数代码的分隔符
function* gen() {
console.log('11111');
yield '求各路';
console.log('22222');
yield '神仙';
console.log('55555');
yield '保佑我';
console.log('66666');
yield '找工作顺利'
}
let iterator = gen();
iterator.next(); //第一次调用next 11111
iterator.next();
iterator.next();
iterator.next();
iterator.next();
yield将函数分割为:
结果:
因为是迭代器对象,所以可以遍历
function* gen() {
yield '求各路';
yield '神仙';
yield '保佑我';
yield '找工作顺利'
}
let iterator = gen();
for(let v of iterator){
console.log(v);
}
每一次调用返回的结果是yield后面的表达式
这样更清楚:
function* gen() {
yield '求各路';
yield '神仙';
yield '保佑我';
yield '找工作顺利'
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
生成器函数的参数传递
整体函数和next方法都可以传参
function *gen(arg) {
console.log(arg);
let r1 = yield 1111;
console.log(r1);
let r2 = yield 2222;
console.log(r2);
let r3 = yield 3333;
console.log(r3)
}
let iterator = gen('AAA');
console.log(iterator.next());
//next方法可以传入实参
console.log(iterator.next('BBB')); //第二次调用next传入的参数作为第一个yield语句整体返回的结果
console.log(iterator.next('CCC')); //第三次调用next传入的参数作为第二个yield语句整体返回的结果
console.log(iterator.next('DDD')); //第四次调用next传入的参数作为第三个yield语句整体返回的结果
生成器函数在异步编程中的表现
常见异步编程 文件操作 网络操作 (ajax,request) 数据库操作
栗子1:
//1s后后台打印1111 2s后打印2222 3s后打印3333
//解决回调地狱
/*setTimeout(function () {
console.log('1111');
setTimeout(function () {
console.log('2222');
setTimeout(function () {
console.log('3333');
},3000)
},2000)
},1000);*/
function one() {
setTimeout(() => {
console.log('1111');
iterator.next();
},1000)
}
function two() {
setTimeout(() => {
console.log('2222');
iterator.next();
},2000)
}
function three() {
setTimeout(() => {
console.log('3333');
iterator.next();
},3000)
}
function *gen() {
yield one();
yield two();
yield three();
}
let iterator = gen();
iterator.next();
栗子2:
//模拟 获取用户数据 再订单数据 再商品数据 是有先后顺序的
function getUsers() {
setTimeout(() => {
let data = '用户数据';
//调用next方法,并将data传入,方便在外部操作数据
iterator.next(data); //这个实参将作为第一个yield返回结果
},1000)
}
function getOrders() {
setTimeout(() => {
let data = '订单数据';
iterator.next(data);
},1000)
}
function getGoods() {
setTimeout(() => {
let data = '商品数据';
iterator.next(data);
},1000)
}
function *gen(){
let users = yield getUsers();
console.log(users);
let orders = yield getOrders();
console.log(orders);
let goods = yield getGoods();
console.log(goods);
}
let iterator = gen();
iterator.next();