33 lines
1.1 KiB
JavaScript
33 lines
1.1 KiB
JavaScript
export default async function* combine(iterable) {
|
|
const asyncIterators = Array.from(iterable, o => o[Symbol.asyncIterator]());
|
|
const results = [];
|
|
let count = asyncIterators.length;
|
|
const never = new Promise(() => {});
|
|
function getNext(asyncIterator, index) {
|
|
return asyncIterator.next().then(result => ({
|
|
index,
|
|
result,
|
|
}));
|
|
}
|
|
const nextPromises = asyncIterators.map(getNext);
|
|
try {
|
|
while (count) {
|
|
const {index, result} = await Promise.race(nextPromises);
|
|
if (result.done) {
|
|
nextPromises[index] = never;
|
|
results[index] = result.value;
|
|
count--;
|
|
} else {
|
|
nextPromises[index] = getNext(asyncIterators[index], index);
|
|
yield result.value;
|
|
}
|
|
}
|
|
} finally {
|
|
for (const [index, iterator] of asyncIterators.entries())
|
|
if (nextPromises[index] != never && iterator.return != null)
|
|
iterator.return();
|
|
// no await here - see https://github.com/tc39/proposal-async-iteration/issues/126
|
|
}
|
|
return results;
|
|
}
|