我有一个功能
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
类似,但不会扔掉剩余的发电机。
下面给出的程序维护一系列承诺
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);
})();