You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过MessageChannel传递异步生成器?重构remoteGenerator为异步生成器

重构 RemoteGenerator 为异步生成器

以下是实现跨上下文生成器交互的原始代码:

function remoteGenerator(port) {
  const createPromise = () => {
    let handlers;
    return {
      promise: new Promise(
        (resolve, reject) => (handlers = { resolve, reject })
      ),
      get handlers() {
        return handlers;
      },
    };
  };
  const createIterator = (run) => {
    const iterator = {
      next: run,
      return: (arg) => run(arg, 'return'),
      [Symbol.asyncIterator]: () => iterator,
    };
    return iterator;
  };

  let done = false;
  let { promise, handlers } = createPromise();
  const step = createIterator((arg, name = 'next') => {
    const original = promise;
    if (done) return original;
    port.postMessage({ name, arg });
    promise = promise.then(() => {
      if (done) return original;
      const next = createPromise();
      handlers = next.handlers;
      return next.promise;
    });
    return original;
  });

  port.onmessage = (evt) => {
    done = evt.data.done;
    handlers[evt.data.handler]({ done: evt.data.done, value: evt.data.value });
  };
  return step;
}

// usage
async function* startCounterAsync(delay = 1000) {
  let i = 0;
  while (i < 10) {
    yield i++;
    await new Promise((r) => setTimeout(r, delay));
  }
}

const startRemoteGenerator = result => {
  const mc = new MessageChannel()
  mc.port1.onmessage = async (evt) => {
    let nextResult;
    try {
      nextResult = await result[evt.data.name](evt.data.arg);
      mc.port1.postMessage({
        name: nextResult.done ? 'return' : 'next',
        handler: 'resolve',
        value: nextResult.value,
        done: nextResult.done,
      });
    } catch (err) {
      mc.port1.postMessage({
        name: 'return',
        handler: 'reject',
        value: err,
        done: true,
      });
    }
    nextResult.done && port.close();
  };
  return remoteGenerator(mc.port2);
}

for await (let value of startRemoteGenerator(startCounterAsync())) {
  console.log(value);
}

remoteGenerator 函数接收 MessageChannel 的一个端口,与消息通道另一端的生成器或异步生成器交互,为不同上下文的执行提供透明接口。

现在希望将 remoteGenerator 重构为异步生成器本身,但存在核心障碍:无法提前知晓远端生成器会返回值还是产出值。为了向远端生成器传递参数,需要在本地执行 yield,而该操作应返回远端生成器产出的值,但似乎无法取消或替换正在进行的 yield 为 return(设置 { done: true })。

目前找到的解决方案是使用包装函数:

async function* remoteGeneratorWrapper(port) {
  const it = remoteGenerator(port);
  yield* it;
  return (await it.return()).value;
}

但希望简化方案,去掉中间异步迭代器。

内容的提问来源于stack exchange,提问作者Eugene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:45:23