## Generator
Generator 函數是 ES6 提供的一種異步編程解決方案,語法行為與傳統函數完全不同。
執行 Generator 函數會返回一個遍歷器對象,也就是說,Generator 函數除了狀態機,還是一個遍歷器對象生成函數。返回的遍歷器對象,可以依次遍歷 Generator 函數內部的每一個狀態。
形式上,Generator 函數是一個普通函數,但是有兩個特征。一是,function關鍵字與函數名之間有一個星號;二是,函數體內部使用yield表達式,定義不同的內部狀態。
```
function* gen() {
yield 'one'
yield 'two'
yield 'three'
}
g = gen()
let a = g.next()
let b = g.next()
let c = g.next()
let d = g.next()
console.log([a, b, c, d])
// 0: {value: "one", done: false}
// 1: {value: "two", done: false}
// 2: {value: "three", done: false}
// 3: {value: undefined, done: true}
```
使用 next 方法,可以訪問 生成器 的下一個狀態,包括 value 和 done,分別表示 當前狀態 的值 和 是否還有下一個值。
### for-of 遍歷
我們甚至可以使用 for-of 循環遍歷輸出 生成器的所有狀態值
```
function* gen() {
yield 'one'
yield 'two'
yield 'three'
}
g = gen()
for (let i of g) {
console.log(i)
}
```
或者
```
function* gen() {
yield 'one'
yield 'two'
yield 'three'
}
for (let i of gen()) {
console.log(i)
}
```
輸出
```
one
two
three
```
### 與異步函數結合
使用 Generator 函數管理流程,遇到異步操作的時候,通常返回一個Promise對象。
```
const g = function* () {
yield Promise.resolve('foo');
yield Promise.resolve('bar');
yield Promise.resolve('baz');
}
function run (generator) {
const it = generator();
function next (result) {
if (result.done) {
return result.value;
}
return result.value.then(value => {
console.log(value)
return next(it.next());
});
}
next(it.next());
}
run(g);
```