ES6个人学习整理(七)——Generator

语法

个人理解:Generator是一个代码生成器,每次调用,生成一块代码。

特征:

  1. function和函数名之间有一个*
  2. 函数体内是用yield关键词(return表示结束)

方法:

  • next()
  • throw()
  • return()

一个简单的demo

function* Gen () {
    yield 'Hello';
    yield 'Generator';
    return '!';
}
let gen = new Gen();
console.log(gen.next());  // Hello
console.log(gen.next());  // Generator
console.log(gen.next());  // !

或者可以这样访问

for (let g of Gen()) {
    console.log(g)
}

next参数的问题

next中可以添加一个参数,作为下一个yield或者return的参数

function* Gen () {
    let a = 1;
    let b = 2;
    let c = yield a + b;
    let d = yield c - a;
    return d;
}
let gen = new Gen();
let g1 = gen.next();
console.log(g1.value);  // 3
let g2 = gen.next(g1);
console.log(g2.value);  // 2 
let g3 = gen.next(g3);
console.log(g3.value);  // 2

yield* 语句

在Generator中直接调用另一个Generator函数是不会起作用的,需要使用yield*语句,起作用相当于将两个Generator合并

function* Gen() {
    yield 'start';
    yield* test();
    yield 'end';
}
function* test () {
    yield 'test1';
    yield 'test2';
}

for (let g of Gen()) {
    console.log(g); 
}
// 输出结果
// start
// test1
// test2
// end

应用

基本的应用场景大概有两类
1. 流程控制(一搬用作UI上的loading)
2. 状态机(通过传入flag来控制)

结合Promise实现简单的co

简单的介绍一下co的实现

    其实就是一个迭代器,检测到未执行完毕就再执行一次,如果执行完毕的话就调用resolve,中途出现错误的情况就调用reject。
    需要注意的地方就两个,一个是将前一个next返回的结果传入到下一个next当做参数,另一个是讲一切非Peomise对象转化为Peomise对象
    在上一篇记录中曾用Promise对ajax进行封装,配合上co,可以发挥更大的威力
// co.js
export default function (Gen) {
    return new Promise(function (resolve, reject) {
        let gen = new Gen();
        next(data) => {
            let current = data ? gen.next(data) : gen.next();
            current.value = current.value instanceof Promise ? current.value : Promise.resolve(current.value);
            if(!current.done) {
                current.value
                .then(_data = > next(_data))
                .catch(error => reject(new Error(error)))
            } else {
                resolve(current.value);
            }
        }
    })
}

// test.js
import $co from './co';
$co(function* () {
    let a = 1;
    let b = 2;
    let c = yield a + b;
    let d = yield c - a;
    return d;
})
.then(message => console.log(message))
.catch(error => console.error(error))

你可能感兴趣的:(ES6,ES6)