Generator
生成器,生成Iterator接口对象的生成器
yield 可暂停函数,yield 后面的值可返回出去,且不终结函数进行
故generator函数一次执行可返回多个值
// Generator函数格式 (带*)
function* fn2() {
yield 1;
yield 2;
return 3;
}
fn(); // 不输出
修改成以下代码:
function* fn2() {
yield console.log(1);
yield console.log(2);
return console.log(3);
}
let iter = fn2(); // 返回Iterator 接口对象
iter.next(); // 1
iter.next(); // 2
iter.next(); // 3
以上代码需要手动设置next,不太方便
可用for of 遍历
for 内部默认调用对象的next方法
所以通过for 遍历generator函数生成的对象,不需要手动的写next,因为next首次执行完之后,会自动调用下一次
function* fn2() {
yield console.log(1);
yield console.log(2);
return console.log(3);
}
let iter = fn2(); */// 返回Iterator 接口对象
for (let key of iter) {}
动态传值
function* foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var a = foo(5);
a.next(); // Object{ value: 6, done: false }
a.next(); // Object{ value: NaN, done: false }
// 理论应该返回 12,为什么返回NaN?
// 因为上一次的yield返回给下一次next 的值默认是 undefined
a.next(); // Object{ value: NaN, done: true }
var b = foo(5);
b.next(); // Object{ value: 6, done: false }
b.next(12); // Object{ value: 8, done: false }
// 输出 8??因为当next 传入12时,那么上次的yield返回的值为12,然后再*2 ,再除3
b.next(23); // Object{ value: 42, done: true }
// y=24 x=5 z=13
yield*
function* f00() {
yield 'a';
yield 'b';
}
// Generator默认不允许在内部调用另一个Generator函数
function* bar() {
yield 'x';
foo(); // // Generator默认不允许在内部调用另一个Generator函数,所以这一步无用
yield 'y';
}
function* bar() {
yield 'x';
yield* foo(); // 使用yield* 才使这一步有意义,指的调用一个Generator函数,而不是普通函数
yield 'y';
}
for (let v of bar()) {
console.log(v);
}
解决异步编程的完美方案 async
因为它是使用Generator和Promise高度封装的
ES2017引入async(sync: 同步)
本质是 Generator函数的语法糖
这就是异步函数,跟普通函数没有什么区别
那它怎么组织代码的呢??因为它的内部有个全新的关键字 await
async function fn() {
/!*await "这个操作有了结果了,才会自动继续向后执行";*!/
// 相当于 yield ,但是yield启动的时候必须手动 next
// 之所以是Generator的语法糖,就是因为 将yield 换成await 的时候,会自动next
const res1 = await "异步1";
const res2 = await "异步2";
}
异步操作返回值出来,如果setTimeout 返回的结果要让 res 接收到,要用Promise
async function fn() {
// 异步操作返回值出来,如果setTimeout 返回的结果要让 res 接收到,要用Promise
/*const res = await setTimeout();*/
const res = await new Promise(resolve => {
setTimeout(() => {
console.log("异步操作完成");
resolve("异步1要返回的数据");
}, 100);
})
console.log(res);
}
fn();
其他写法
// 表达式写法
const fn = async function() {};
// 箭头函数
const fnn = async () => {};