有没有办法从任何生成器中产生

问题描述 投票:0回答:1

我有一个功能

async function* values(input) {
    ...
}

这将根据输入产生一些值。

现在我有一组输入,比如说

[1,2,3,4,5]
,我想创建另一个生成器函数,该函数将使用这些输入并为每个输入调用
values
。 每当任何
values
调用产生时,我都想从包装生成器函数中产生返回。
该函数按顺序产生生成器:

function* generateValues() {
     const inputs = [1,2,3,4,5];

     const generators = inputs.map(input => values(input));

     for (const generator of generators) {
          yield await generator.next();
     }
}

但是我想在任何发电机发电时立即发电,并继续发电直到所有发电机都耗尽

我想用以下内容替换上面的 for 循环:

for await (const value of Generator.any(generators)) {
    yield value;
}

即我正在寻找类似

Generator.any
的东西,它与
Promise.any
类似,但不会扔掉剩余的发电机。

javascript generator
1个回答
0
投票

下面给出的程序维护一系列承诺

nexts
,以便
nexts[i]
解析为
generators[i]
和索引
i
生成的值。循环重复使用
Promise.any
来获取此值,并使用下一个值的承诺更新
nexts[i]
。但如果生成器是
done
,则承诺实际上会从
nexts
中删除。当所有承诺都被删除时,循环结束。

async function* values(input) {
  await new Promise(function (resolve, reject) {
    setTimeout(resolve, 1000 - input * 100);
  });
  yield input;
  await new Promise(function (resolve, reject) {
    setTimeout(resolve, input * 200);
  });
  yield input + 10;
}

async function awaitNext(generator, index) {
  const next = await generator.next();
  return { index, next };
}

async function* generateValues() {
  const inputs = [1, 2, 3, 4, 5];
  const generators = inputs.map((input) => values(input));
  let running = generators.length;
  const nexts = generators.map(awaitNext);
  while (true) {
    const { index, next } = await Promise.any(nexts);
    if (next.done) { // Remove this promise
      nexts[index] = new Promise(() => {});
      if (--running === 0) return; // All promises removed
    } else {
      nexts[index] = awaitNext(generators[index], index); // Update this promise for the next value
      yield next.value;
    }
  }
}

(async function () {
  const gen = generateValues();
  for await (const i of gen) console.log(i);
})();

© www.soinside.com 2019 - 2024. All rights reserved.