1.什么是Generator函数?
- Generator 函数是 ES6 提供的一种异步编程解决方案
- Generator 函数内部可以封装多个状态, 因此又可以理解为是一个状态机
2.如何定义Generator函数
- 只需要在普通函数的function后面加上*即可
3.Generator函数和普通函数区别
- 3.1 调用Generator函数后, 无论函数有没有返回值, 都会返回一个迭代器对象
// 普通函数 function fn(){ } console.log(fn) // generator函数 function* gen(){ } console.log(gen())
普通函数和generator函数的区别.png
- 3.2 调用Generator函数后, 函数中封装的代码不会立即被执行
function* gen(){ console.log("小单今天要比昨天有进步哦!") } console.log(gen())
generator.png
4.真正让Generator具有价值的是yield关键字
- 4.1在Generator函数内部使用yield关键字定义状态
普通的函数不能使用yield关键字
image.png - 4.2并且yield关键字可以让 Generator内部的逻辑能够切割成多个部分,通过
next()
函数依次执行各个被切割的部分。通过调用迭代器对象的next方法执行一个部分代码,执行哪个部分就会返回哪个部分定义的状态
function* gen() { console.log("124"); let res = yield "aaa"; console.log(res); console.log("456"); yield 1 + 1; console.log("789"); yield true; } gen(); let it = gen(); console.log(it); console.log(it.next()); console.log(it.next()); console.log(it.next());
image.png
- 4.3通过调用迭代器对象的next方法执行最后一个部分继续使用next函数会返回undefined
image.png - 4.4 在调用next方法的时候可以传递一个参数, 这个参数会传递给上一个yield
function* gen() { console.log("124"); let res = yield "aaa"; console.log(res); console.log("456"); yield 1 + 1; console.log("789"); yield true; } gen(); let it = gen(); console.log(it); console.log(it.next()); console.log(it.next("shanjialan")); console.log(it.next()); console.log(it.next());
generator传参.png
Generator的应用
Generator应用场景一:返回多个数值
function* fn(a, b) { yield a + b; yield a - b; } let res1 = fn(10, 5); console.log(res1.next().value); console.log(res1.next().value);
Generator应用场景二:可以利用generator函数快速部署可迭代对象
1.不用generator,使用iterator
let obj = { name: "shanjialan", age: 20, [Symbol.iterator]() { let keys = Object.keys(this); let index = 0; let that = this; return { next() { if (index < keys.length) { return { value: that[keys[index++]], done: false } } else { return { value: undefined, done: true } } } } } }
2.使用generator
let obj = { name: "shanjialan", age: 15, } function* fn3() { let keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { yield obj[keys[i]]; } } obj[Symbol.iterator] = fn3; for (let val of obj) { console.log(val); }
Generator应用场景三:同步代码异步表示
function request() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve("拿到的数据"); }, 1000); }); } function* gen2() { yield request(); yield request(); yield request(); } let res3 = gen2(); res3.next().value.then(function(data) { console.log(data, 1); return res3.next().value; }).then(function(data) { console.log(data, 2); return res3.next().value; }).then(function(data) { console.log(data, 3); return res3.next().value; })
这种方法写起来非常复杂,代码量不比promise少,到是这个ES8的一种解决方案asyc…await
的实现原理
asyc…await
- 1.async函数
async函数是ES8中新增的一个函数, 用于定义一个异步函数
async函数函数中的代码会自动从上至下的执行代码 - 2.await操作符
await操作符只能在异步函数 async function 中使用
await表达式会暂停当前 async function 的执行,等待 Promise 处理完成。
若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,然后继续执行 async function。
function request() { return new Promise(function (resolve, reject) { setTimeout(function () { resolve("拿到的数据"); }, 1000); }); } async function gen() { let res1 = await request(); console.log(res1, 1); let res2 = await request(); console.log(res2, 2); let res3 = await request(); console.log(res3, 3); } gen();
将generator function后面的*换成function前面的async,将yield改为await即可