Generator(生成器)

邹嘉石
2023-12-01

generator是ES6中非常强悍的一个新特性。

用generator 实现斐波那契数列,如下:

function* fifo (){
    let a = 0;
    let b = 1;

    yield a;
    yield b;

    while(true){
        let next = a+b;
        a = b;
        b = next;
        yield next;
    }
}

let generator = fifo();

for ( let i = 0 ; i < 10; i++ ){
    console.log( generator.next().value)
}

用这个例子学习一下generator。

# 定义一个generator

generator函数与普通函数的语法区别在于,在function语句之后和函数名之前,有一个*作为generator函数的标识符。

function* fifo(){
    //...
}

也可以使用表达式定义

const fifo = function*(){
    //...
}

# yield语句

yield语句的作用和return语句有些相似,但并非退出函数体,而是切出当前函数的运行时,同时可以将一个值带到主线程中。

yield语句可返回多次。

# 启动generator

generator函数不能直接作为普通的函数使用,因为在调用时无法直接执行其中的逻辑代码。执行generator函数会返回一个generator对象,用于运行generator内容和接受其中的值。

let generator = fifo();

# generator VS普通函数

generator还有另一个巨大的好处,就是把异步回调代码变成“同步”代码

没有generator之前的黑暗时代,用AJAX时需要这么写代码:

ajax('http://url-1', data1, function (err, result) {
    if (err) {
        return handle(err);
    }
    ajax('http://url-2', data2, function (err, result) {
        if (err) {
            return handle(err);
        }
        ajax('http://url-3', data3, function (err, result) {
            if (err) {
                return handle(err);
            }
            return success(result);
        });
    });
});

回调越多,代码越难看。

有了generator的美好时代,用AJAX时可以这么写:

try {
    r1 = yield ajax('http://url-1', data1);
    r2 = yield ajax('http://url-2', data2);
    r3 = yield ajax('http://url-3', data3);
    success(r3);
}
catch (err) {
    handle(err);
}

看上去是同步的代码,实际执行是异步的。

 类似资料: