Advertisement

什么是生成器函数?

阅读量:

在 JavaScript 中定义的特殊函数称为生成器函数(Generator Function),其特征是在运行过程中能够暂停并随后恢复其运行状态。这种特殊功能是通过 function* 语法结构实现的,并且在内部采用 yield 表达式来控制程序流程。每当调用由该生成器函数返回迭代器时,在下一次启动该迭代过程时,默认会从上次暂停的位置继续执行下去;除非当前处于一个可中断的状态并触发下一个 yield 表达式或直接终止整个操作流程为止。

生成器函数的定义和用法

定义生成器函数

生成器函数使用 function* 关键字定义:

复制代码
    function* generatorFunction() {
    yield 'First output';
    yield 'Second output';
    return 'Finished';
    }
调用生成器函数

调用生成器函数会返回一个迭代器对象,该对象具有 next 方法:

复制代码
    const gen = generatorFunction();
迭代生成器函数

通过 next 方法迭代生成器函数,在每次 next 方法被执行时(或称为被调用),生成器函数会推进到下一个 yield 表达式,并返回一个对象 { value: any, done: boolean }。

复制代码
    console.log(gen.next()); // { value: 'First output', done: false }
    console.log(gen.next()); // { value: 'Second output', done: false }
    console.log(gen.next()); // { value: 'Finished', done: true }
    console.log(gen.next()); // { value: undefined, done: true }

生成器函数的特性

暂停与恢复执行机制
当生成器函数遇到 yield 表达式时会暂时停止运行,并将返回其后的值。其状态会被保留下来,在下一次调用 next 方法时会从之前暂停的位置继续执行相应的代码逻辑。

双向通信 : 使用next方法向生成器函数发送参数,并由其接收处理相关事务。

遵循迭代器协议 : 由生成器函数返回的迭代器对象可用于 for...of 循环以及其他需要迭代器的应用场景中。

示例

简单生成器函数
复制代码
    function* simpleGenerator() {
    yield 1;
    yield 2;
    yield 3;
    }
    
    const gen = simpleGenerator();
    
    console.log(gen.next()); // { value: 1, done: false }
    console.log(gen.next()); // { value: 2, done: false }
    console.log(gen.next()); // { value: 3, done: false }
    console.log(gen.next()); // { value: undefined, done: true }
双向通信的生成器函数
复制代码
    function* counter() {
    let count = 0;
    while (true) {
        const increment = yield count;
        if (increment != null) {
            count += increment;
        } else {
            count++;
        }
    }
    }
    
    const countGenerator = counter();
    
    console.log(countGenerator.next().value); // 0
    console.log(countGenerator.next(2).value); // 2
    console.log(countGenerator.next(3).value); // 5
    console.log(countGenerator.next().value); // 6
用于异步操作的生成器函数

生成器函数配合Promise来执行异步操作,并能使其更加接近同步风格

复制代码
    function fetchData(url) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(`Data from ${url}`);
        }, 1000);
    });
    }
    
    function* asyncTaskQueue() {
    const data1 = yield fetchData('https://api.example.com/endpoint1');
    console.log(data1);
    const data2 = yield fetchData('https://api.example.com/endpoint2');
    console.log(data2);
    const data3 = yield fetchData('https://api.example.com/endpoint3');
    console.log(data3);
    }
    
    function run(generator) {
    const iterator = generator();
    
    function handle(result) {
        if (result.done) return;
    
        result.value.then(data => {
            handle(iterator.next(data));
        });
    }
    
    handle(iterator.next());
    }
    
    run(asyncTaskQueue);

生成器函数的优势

  • 灵活度:支持高效的暂停与恢复机制,在处理复杂控制流时展现出强大的适应能力。
  • 双向传输:通过特定指令实现精确的数据双向流动机制。
  • 内存高效:采用逐项生成策略,在大数据处理中显著优化资源利用效率。
  • 异步开发:结合 Promise 技术体系构建出更加流畅的异步操作框架。

在JavaScript中使用生成器函数提供了一种强有力的工具来处理迭代、异步操作以及复杂的控制流。掌握其应用能够显著提高代码的可读性和可维护性。

全部评论 (0)

还没有任何评论哟~