For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/year/pending/proposal-emitter.md.
  • 简体中文
  • Emitter S1

    中文标题:发射器

    提案概览
    提案速览

    该提案引入了一个名为 Emitter 的通用容器,用于处理同步和异步、单一和多个值,统一了 EventTarget 和 EventEmitter 等 API。它提供了可组合的操作符(如 map、filter、reduce、flatten)用于算法变换,旨在实现高性能。提案包含示例和 API 概要,但提供的文本中未提及该提案的阶段/状态。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    ECMAScript 提案:Emitter

    • JavaScript 最通用的容器,覆盖单一和多个值、同步和异步值
    • 操作符构成 Generics,是最终标准库的重要组成部分
    • 可组合的算法变换,与其输入和输出解耦
    • 与语言良好集成,而不是发明大量新概念(例如 Promise、迭代、异步迭代等)
    • 向后兼容地统一平台 API(如 EventTarget 和 EventEmitter 等接口)
    • 超高性能(比 most.js 更快) 且内存高效

    响应式编程示例

    记录 <button> 元素上点击事件的 XY 坐标:

    const { on, map, filter, run } = Emitter
    
    run(
      on(document, 'click')
    , filter(ev => ev.target.tagName === 'BUTTON')
    , map(ev => ({ x: ev.clientX, y: ev.clientY }))
    , coords => console.log(coords)
    )

    将两个按钮的点击映射为 +1 和 -1 的流,合并它们并渲染结果:

    const { on, map, tap, reduce, flatten, render } = Emitter
    
    const inc = map(() => 1, on(buttonA, 'click')) 
    const dec = map(() => -1, on(buttonB, 'click'))
    const counter = reduce(0, flatten(inc, dec))
    const render = tap(total => { output.innerText = String(total) }, counter)
    run(render)

    派生 10 个对等进程,等待它们全部连接,返回这些进程的引用:

    const { run, until, once, flatten, reduce } = Emitter
    const { fork } = require('child_process')
    
    const processes = await run(
      10
    , map(() => fork('peer.js'))
    , map(async peer => {
        await until(d => d == 'connected', on(peer, 'message'))
        return peer
      })
    , flatten()
    , reduce([])
    )

    可迭代编程示例

    从一系列数字中,将它们除以 4,移除任何大于 12 的,然后开始逐一收集它们:

    function* range(from, to) { 
      for (let i = from; i <= to; i++) yield i  
    }
    
    const arr = run(
      range(40, 60)
    , map(d => d / 4)
    , filter(d => d < 12)
    , reduce([])
    )

    逐一转换一系列数字并记录结果:

    for (const d of map(d => d + 1, [1, 2, 3]))
      console.log('transformed output', d)

    每当用户按下 CTRL+C 时记录:

    for await (const d of filter(([n]) => n == 3, process.stdin))
      console.log('SIGINT!')

    API

    转换

    过滤

    运行

    创建


    背景

    有关这一领域的总体背景,尤其是从语言角度出发,Rich Hickey 关于 Clojure 的 core.async 库的动机、设计和使用的演讲 是必看的。

    作为比较,以下是 Rob Pike 在演讲中讨论的原始示例,使用复制搜索服务器减少尾部延迟

    const { race, timeout, until, reduce, flatten } = Emitter 
    
    const results = await race(
      timeout(80)
    , until(3, reduce([], flatten(
        race(web1(query), web2(query))
      , race(img1(query), img2(query))
      , race(vid1(query), vid2(query))
      )))
    )

    熟悉这一领域的现有 JavaScript 库也是有用的:

    更多细节包含在并将在 FAQ 中记录。