首页 > web前端 > js教程 > 正文

JS如何实现生成器协程?协程的调度

月夜之吻
发布: 2025-08-21 13:46:01
原创
1012人浏览过
JavaScript通过生成器函数function*和yield实现协程,调用生成器函数返回生成器对象,执行时遇到yield暂停并返回值,通过next()方法恢复执行且可传参,实现双向通信;生成器保持内部状态,支持惰性求值和分步执行,常用于异步流程控制;为调度生成器协程,需编写执行器函数run,其递归调用next()并处理yield出的Promise,实现类似async/await的异步串行化执行,从而完成合作式多任务调度。

js如何实现生成器协程?协程的调度

JavaScript 中的生成器(Generator)提供了一种非常巧妙的方式来实现协程(Coroutine)。简单来说,它允许函数在执行过程中暂停,然后根据外部指令在之后恢复执行,甚至可以双向传递数据。这种“暂停-恢复”的能力,正是构建协程的核心。至于调度,通常需要一个外部的“执行器”或“调度器”来管理生成器的推进,特别是在处理异步操作时,它会负责在正确时机调用生成器的

next()
登录后复制
方法。

要理解JS如何实现生成器协程,我们得从

function*
登录后复制
这个语法糖说起。它定义了一个生成器函数,执行它并不会立即运行函数体,而是返回一个生成器对象(Generator Object),这个对象遵循迭代器协议。

关键在于

yield
登录后复制
关键字。当生成器函数执行到
yield
登录后复制
表达式时,它会暂停执行,并将
yield
登录后复制
后面的值作为
next()
登录后复制
方法的结果返回。函数的状态会被保存下来,等待下一次
next()
登录后复制
调用。

看个简单的例子:

function* myCoroutine() {
    console.log('协程开始');
    let x = yield '第一次暂停,请给我一个值';
    console.log('协程恢复,得到了值:', x);
    let y = yield '第二次暂停,再给我一个值';
    console.log('协程再次恢复,得到了值:', y);
    return '协程结束';
}

const co = myCoroutine();

console.log(co.next().value); // 输出:协程开始 \n 第一次暂停,请给我一个值
console.log(co.next('Hello').value); // 输出:协程恢复,得到了值: Hello \n 第二次暂停,再给我一个值
console.log(co.next('World').value); // 输出:协程再次恢复,得到了值: World \n 协程结束
登录后复制

在这个例子里,

myCoroutine
登录后复制
就是一个简单的协程。它通过
yield
登录后复制
将控制权交出去,又通过
next()
登录后复制
被外部唤醒。
next()
登录后复制
方法还可以接收参数,这个参数会成为上一个
yield
登录后复制
表达式的返回值,实现了协程与外部的双向通信。这就是协程最基础的形态:合作式多任务,函数自己决定何时暂停,何时交出控制权。

生成器函数与普通函数有何本质区别?它们如何实现执行流的“暂停”与“恢复”?

我觉得,理解生成器和普通函数最大的不同,就像理解电影和照片的区别。普通函数就像一张照片,一旦拍下(执行),就定格了,从头到尾一次性完成。而生成器函数则像一部电影,你可以在任何一个“暂停”点(

yield
登录后复制
)停下来,观察当前画面,甚至给它一些指令,然后它再继续播放。

具体来说,普通函数被调用后,会一直执行直到遇到

return
登录后复制
语句或函数体结束。它的局部变量和执行状态在每次调用后都会被销毁。

豆包AI编程
豆包AI编程

豆包推出的AI编程助手

豆包AI编程 483
查看详情 豆包AI编程

生成器函数则不同。

  1. *`function` 语法:** 这是它最明显的标志。
  2. 惰性执行: 调用生成器函数不会立即执行其内部代码,而是返回一个“生成器对象”(Generator Object)。这个对象本身就是一个迭代器(Iterator)和可迭代对象(Iterable)。
  3. yield
    登录后复制
    关键字:
    这是实现暂停和恢复的魔法。当生成器执行到
    yield
    登录后复制
    表达式时,它会暂停当前函数的执行,将
    yield
    登录后复制
    后面的值“产出”(yield)给外部,并将当前的执行上下文(包括局部变量、程序计数器等)完整地保存下来。
  4. next()
    登录后复制
    方法:
    外部通过调用生成器对象的
    next()
    登录后复制
    方法来“推动”生成器继续执行。每次调用
    next()
    登录后复制
    ,生成器都会从上次
    yield
    登录后复制
    暂停的地方恢复执行,直到遇到下一个
    yield
    登录后复制
    return
    登录后复制
    next()
    登录后复制
    方法返回一个对象
    { value: any, done: boolean }
    登录后复制
    value
    登录后复制
    yield
    登录后复制
    return
    登录后复制
    的值,
    done
    登录后复制
    表示生成器是否已执行完毕。
  5. 状态保持: 这是最关键的一点。生成器能够“记住”它上次暂停时的所有状态,所以当它恢复时,就像从未离开过一样。

这种独特的行为模式,让生成器非常适合处理需要分步执行、或者需要外部控制流程的场景,协程只是其中一个非常典型的应用。

JavaScript中,我们通常如何调度生成器协程,以实现复杂的异步流程控制?

协程的魅力在于“调度”,也就是如何管理这些可暂停的执行流。在JavaScript中,由于它是单线程的,我们说的“调度”并非操作系统层面的时间片轮转,而是一种“合作式调度”:生成器自己决定何时暂停,并将控制权交还给调度器。调度器则负责在合适的时候,比如一个异步操作完成后,再次唤醒生成器。

最常见的调度模式就是编写一个“执行器”(Runner)或“调度器”(Scheduler)函数。这个函数会接收一个生成器对象作为输入,然后通过递归或循环的方式,不断调用生成器的

next()
登录后复制
方法,直到生成器执行完毕。

当生成器

yield
登录后复制
出一个值时,调度器需要判断这个值的类型。如果它是一个Promise,那么调度器就会等待这个Promise解析(resolved)后,再将解析结果作为参数传给生成器的下一个
next()
登录后复制
调用。这正是
async/await
登录后复制
底层逻辑的简化版。

我们来构建一个简单的异步协程调度器:

function run(generatorFunc) {
    const generator = generatorFunc(); // 获取生成器实例

    function step(nextData) {
        const result = generator.next(nextData); // 推进生成器

        if (result.done) {
            return Promise.resolve(result.value); // 生成器完成,返回最终值
        }

        // 如果yield出来的是一个Promise,就等待它
        return Promise.resolve(result.value)
            .then(data => step(data)) // Promise成功,将结果传回生成器继续执行
            .catch(error => generator.throw(error)); // Promise失败,将错误抛回生成器
    }

    return step(); // 启动调度
}

// 示例:一个包含异步操作的生成器协程
function* asyncTask() {
    console.log('开始异步任务
登录后复制

以上就是JS如何实现生成器协程?协程的调度的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门推荐
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号