Skip to content

Instantly share code, notes, and snippets.

@m93a
Last active January 13, 2024 17:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m93a/6b77abaa7d45c505903b43f68d8d2225 to your computer and use it in GitHub Desktop.
Save m93a/6b77abaa7d45c505903b43f68d8d2225 to your computer and use it in GitHub Desktop.
export async function* asyncCombine<S, T>(
a: AsyncIterable<S>,
b: AsyncIterable<T>,
): AsyncIterable<[S | undefined, T | undefined]> {
let aVal: S | undefined;
let bVal: T | undefined;
let aDone = false;
let bDone = false;
const aIter = a[Symbol.asyncIterator]();
const bIter = b[Symbol.asyncIterator]();
let aPromise: Promise<void> | undefined;
let bPromise: Promise<void> | undefined;
const aRequestNext = () =>
aPromise = aIter.next().then((res) => {
if (res.done) aDone = true;
aVal = res.value;
if (!aDone) aRequestNext();
});
const bRequestNext = () =>
bPromise = bIter.next().then((res) => {
if (res.done) bDone = true;
bVal = res.value;
if (!bDone) bRequestNext();
});
aRequestNext();
bRequestNext();
while (true) {
if (!aDone && !bDone) await Promise.any([aPromise, bPromise]);
else if (aDone) await bPromise;
else if (bDone) await aPromise;
if (aDone && bDone) return;
yield [aVal, bVal];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment