Skip to content

Instantly share code, notes, and snippets.

@n1ru4l
Created December 2, 2020 08:35
Show Gist options
  • Save n1ru4l/ba1055dccc9dcef79f366e57a9a98a3d to your computer and use it in GitHub Desktop.
Save n1ru4l/ba1055dccc9dcef79f366e57a9a98a3d to your computer and use it in GitHub Desktop.
Without using Symbol.asyncIterator
type Deferred<T> = {
resolve: (value: T) => void;
reject: (value: unknown) => void;
promise: Promise<T>;
};
function createDeferred<T>(): Deferred<T> {
const d = {} as Deferred<T>;
d.promise = new Promise<T>((resolve, reject) => {
d.resolve = resolve;
d.reject = reject;
});
return d;
}
export function makePushPullAsyncIterableIterator<T>() {
let isRunning = true;
const pushQueue: Array<T> = [];
let d = createDeferred<"FINISH" | "NEW_VALUE">();
const iterator = (async function* PushPullAsyncIterableIterator(): AsyncIterableIterator<
T
> {
while (true) {
if (pushQueue.length > 0) {
yield pushQueue.shift()!;
} else {
const res = await d.promise;
if (res === "FINISH") {
return;
}
}
}
})();
function push(value: T) {
if (isRunning === false) {
// TODO: Should this throw?
return;
}
pushQueue.push(value);
d.resolve("NEW_VALUE");
d = createDeferred();
}
const oReturn = iterator["return"]?.bind(iterator);
iterator["return"] = (...args) => {
d.resolve("FINISH");
return (
oReturn?.(...args) ?? Promise.resolve({ done: true, value: undefined })
);
};
return [push, iterator] as const;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment