Skip to content

Instantly share code, notes, and snippets.

@mindplay-dk
Created December 27, 2021 08:54
Show Gist options
  • Save mindplay-dk/76d07c2f065c73213556349363c8fb5d to your computer and use it in GitHub Desktop.
Save mindplay-dk/76d07c2f065c73213556349363c8fb5d to your computer and use it in GitHub Desktop.
Synchronous push API to asynchronous generator (event sink)
export type Emitter<T> = (emit: { (value: T): void }) => Promise<void>;
export function createSink<T>(emitter: Emitter<T>): AsyncIterable<T> {
const sink: T[] = [];
let onData = () => { };
let accept = (value: T) => {
sink.push(value);
onData();
};
const done = emitter(value => accept(value));
done.then(() => {
accept = () => {
throw new Error(`late value!`); // TODO improve error message
}
});
function asap() {
if (sink.length) {
return Promise.resolve();
}
const hasData = new Promise<void>(resolve => {
onData = resolve;
});
return Promise.race([hasData, done]);
}
return {
[Symbol.asyncIterator]() {
return {
next() {
return asap().then(() => {
return sink.length > 0
? { done: false, value: sink.shift()! }
: { done: true, value: undefined };
});
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment