# Generator & async/await原理
# Generator
Generator
函数是一个状态机,封装了多个内部状态。
执行 Generator
函数会返回一个遍历器对象,可以依次遍历 Generator
函数内部的每一个状态,但是只有调用next
方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield
表达式就是暂停标志。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
调用及运行结果:
hw.next() // { value: 'hello', done: false }
hw.next() // { value: 'world', done: false }
hw.next() // { value: 'ending', done: true }
hw.next() // { value: undefined, done: true }
由结果可以看出,Generator函数
被调用时并不会执行,只有当调用next
方法、内部指针指向该语句时才会执行,即函数可以暂停,也可以恢复执行。
每次调用遍历器对象的next
方法,就会返回一个有着value
和done
两个属性的对象。
value
属性表示当前的内部状态的值,是yield
表达式后面那个表达式的值;done
属性是一个布尔值,表示是否遍历结束。
也可以通过给next()
传参, 让yield
具有返回值
function* myGenerator() {
console.log(yield '1') //test1
console.log(yield '2') //test2
console.log(yield '3') //test3
}
// 获取迭代器
const gen = myGenerator();
gen.next()
gen.next('test1')
gen.next('test2')
gen.next('test3')
Generator 函数的语法 (opens new window)
# async/await 实现
一句话,它就是 Generator 函数的语法糖。
ES7 中引入了 async/await
,这种方式能够彻底告别执行器和生成器,实现更加直观简洁的代码。
根据 MDN 定义, async
是一个通过异步执行并隐式返回 Promise
作为结果的函数。
可以说 async
是Generator函数的语法糖,并对Generator函数进行了改进。
const foo = async () => {
let response1 = await fetch('https://xxx')
console.log('response1')
console.log(response1)
let response2 = await fetch('https://xxx')
console.log('response2')
console.log(response2)
}
一比较就会发现,async
函数就是将 Generator 函数的星号(*)替换成async
,将yield
替换成await
,仅此而已。
async
函数对 Generator 函数的改进,体现在以下四点:
内置执行器
:async不需要手动调用next()就能自动执行下一步更好的语义
:async和await,比起星号和yielz,语义更清楚了。更广的适用性
:co模块约定,yield
命令后面只能是Thunk
函数或Promise
对象,而async
函数的await
命令后面,可以是Promise
对象和原始类型的值返回值是 Promise
:async函数返回值是Promise对象,比 Generator 函数返回的 Iterator 对象方便,可以直接使用then()
方法进行调用。