全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 8 分钟 ✍️ juanwangdev

JavaScript Generator 函数与异步生成器

Generator 函数是可暂停的函数,yield 暂停执行并产出值,异步生成器结合 Promise 实现复杂的异步流程控制。

Generator 函数基础

JavaScript
// 定义:function* 声明
function* generator() {
    yield 1;
    yield 2;
    yield 3;
}

// 创建迭代器
const gen = generator();

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 }

yield 表达式

JavaScript
function* gen() {
    const a = yield 'first';   // yield 返回外部传入的值
    console.log('收到:', a);   // 收到: 传入值

    const b = yield 'second';
    console.log('收到:', b);

    return 'end';
}

const g = gen();
console.log(g.next());           // { value: 'first', done: false }
console.log(g.next('传入值'));    // { value: 'second', done: false },打印"收到: 传入值"
console.log(g.next('另一个值'));  // { value: 'end', done: true },打印"收到: 另一个值"

// 第一个 next() 的参数被忽略(Generator 刚启动)

Generator 方法

JavaScript
function* gen() {
    try {
        yield 1;
        yield 2;
        yield 3;
    } catch (e) {
        console.log('捕获错误:', e.message);
    }
}

const g = gen();

// next():继续执行
console.log(g.next());  // { value: 1, done: false }

// return():提前终止
console.log(g.return('终止'));  // { value: '终止', done: true }
console.log(g.next());          // { value: undefined, done: true }

// throw():在 yield 处抛出错误
const g2 = gen();
g2.next();  // 执行到 yield 1
g2.throw(new Error('迭代器错误'));  // 在 yield 1 处抛出错误

yield* 委托

JavaScript
// 委托给另一个 Generator
function* inner() {
    yield 'a';
    yield 'b';
}

function* outer() {
    yield 1;
    yield* inner();  // 委托给 inner
    yield 2;
}

const gen = outer();
console.log(gen.next());  // { value: 1, done: false }
console.log(gen.next());  // { value: 'a', done: false }
console.log(gen.next());  // { value: 'b', done: false }
console.log(gen.next());  // { value: 2, done: false }
console.log(gen.next());  // { value: undefined, done: true }

// yield* 可委托任何可迭代对象
function* gen() {
    yield* [1, 2, 3];  // 委托数组
    yield* 'hello';    // 委托字符串
}

const g = gen();
console.log([...g]);  // [1, 2, 3, 'h', 'e', 'l', 'l', 'o']

异步生成器

JavaScript
// async function*:异步生成器
async function* asyncGen() {
    yield await fetch('/api/1');
    yield await fetch('/api/2');
    yield await fetch('/api/3');
}

// 使用 for await...of
(async () => {
    for await (const response of asyncGen()) {
        const data = await response.json();
        console.log(data);
    }
})();

// 模拟异步数据流
async function* fetchData(urls) {
    for (const url of urls) {
        try {
            const response = await fetch(url);
            yield await response.json();
        } catch (e) {
            yield { error: e.message };
        }
    }
}

(async () => {
    const urls = ['/api/a', '/api/b', '/api/c'];
    for await (const data of fetchData(urls)) {
        console.log(data);
    }
})();

Generator 实现异步流程

JavaScript
// 传统回调方式
function fetchUser(id, callback) {
    setTimeout(() => callback({ id, name: 'User' + id }), 100);
}

// Generator + 自动执行器
function* fetchUsers() {
    const user1 = yield fetchUser.bind(null, 1);
    const user2 = yield fetchUser.bind(null, 2);
    console.log(user1, user2);
}

// 自动执行器(类似 co 库)
function run(generator) {
    const gen = generator();

    function next(value) {
        const result = gen.next(value);
        if (result.done) return;

        // 如果 yield 返回函数,执行并传入回调
        if (typeof result.value === 'function') {
            result.value((data) => next(data));
        }
    }

    next();
}

run(fetchUsers);

// Promise 版自动执行器
function promiseRun(generator) {
    const gen = generator();

    function next(value) {
        const result = gen.next(value);
        if (result.done) return Promise.resolve(result.value);

        return Promise.resolve(result.value).then(next);
    }

    return next();
}

Generator 实现状态机

JavaScript
// 状态机:有限状态流转
function* stateMachine() {
    while (true) {
        switch (yield) {
            case 'start':
                console.log('状态: 开始');
                yield 'running';
                break;
            case 'running':
                console.log('状态: 运行中');
                yield 'running';  // 保持运行
                break;
            case 'stop':
                console.log('状态: 停止');
                return 'end';
        }
    }
}

const machine = stateMachine();
machine.next();           // 启动 Generator
machine.next('start');    // 输出"状态: 开始",返回 { value: 'running', done: false }
machine.next('running');  // 输出"状态: 运行中"
machine.next('stop');     // 输出"状态: 停止",返回 { value: 'end', done: true }

实际应用场景

JavaScript
// 惰性计算
function* range(start, end) {
    while (start < end) {
        yield start++;
    }
}

for (const n of range(0, 1000000)) {
    if (n > 10) break;  // 只计算需要的部分
}

// 无限序列
function* fibonacci() {
    let [a, b] = [0, 1];
    while (true) {
        yield a;
        [a, b] = [b, a + b];
    }
}

const fib = fibonacci();
console.log(fib.next().value);  // 0
console.log(fib.next().value);  // 1
console.log(fib.next().value);  // 1
console.log(fib.next().value);  // 2

// 任务队列
function* taskQueue(tasks) {
    for (const task of tasks) {
        yield task();
    }
}

const tasks = [
    () => console.log('任务1'),
    () => console.log('任务2'),
    () => console.log('任务3')
];

const queue = taskQueue(tasks);
queue.next();  // 执行任务1
queue.next();  // 执行任务2

注意事项

  • Generator 函数调用返回迭代器,不立即执行
  • 第一个 next() 参数被忽略,Generator 刚启动无法接收值
  • return() 终止 Generator,执行 finally
  • 异步生成器必须用 async function* 定义
JavaScript
// 第一个 next 参数被忽略
function* gen() {
    const x = yield 'first';
    console.log(x);
}
const g = gen();
g.next('ignored');  // 参数被忽略
g.next('received'); // 输出 'received'

// finally 在 return 时执行
function* gen() {
    try {
        yield 1;
    } finally {
        console.log('清理');
    }
}
const g = gen();
g.next();
g.return();  // 执行 finally,输出 '清理'

要点总结

  • function* 定义 Generator,yield 暂停并产出值
  • next(value) 继续执行,value 成为上一个 yield 的返回值
  • yield* 委托给其他 Generator 或可迭代对象
  • return() 提前终止,throw() 在 yield 处抛出错误
  • async function* 异步生成器,yield 可接 Promise
  • 适用于惰性计算、无限序列、状态机、异步流程控制
  • 配合自动执行器可实现类似 async/await 的效果

📝 发现内容有误?点击此处直接编辑

← 上一篇 JavaScript 构造函数与原型
下一篇 → JavaScript Web Workers 与多线程
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库