Skip to content

Instantly share code, notes, and snippets.

@michaelsbradleyjr
Last active January 15, 2020 22:38
Show Gist options
  • Save michaelsbradleyjr/360f5e3df2c2a0b68481f7ec44a4cdc7 to your computer and use it in GitHub Desktop.
Save michaelsbradleyjr/360f5e3df2c2a0b68481f7ec44a4cdc7 to your computer and use it in GitHub Desktop.
function makeAsyncQueue() {
let promise;
let resolve;
const queue = [];
const setPromise = () => {
promise = new Promise(res => {
resolve = res;
});
};
setPromise();
let isDone;
const send = v => {
if (!isDone) {
queue.push(v);
if (queue.length === 1) resolve();
}
};
const DONE = Symbol("done");
const done = () => {
send(DONE);
};
const generator = async function*() {
let v;
while (true) {
if (!queue.length) await promise;
v = queue.shift();
if (v === DONE) {
isDone = true;
queue.length = 0;
break;
}
if (!queue.length) setPromise();
yield v;
}
};
return {
done,
iterator: generator(),
send
};
}
(async () => {
{
const { done, iterator, send } = makeAsyncQueue();
setTimeout(() => send(1), 1000);
setTimeout(() => send(2), 2000);
setTimeout(() => send(3), 3000);
setTimeout(done, 4000);
setTimeout(() => send(4), 5000); // won't print `x: 4` because it's already done
for await (const x of iterator) {
console.log("x:", x);
}
}
console.log("-----------------");
{
const { iterator, send } = makeAsyncQueue();
for (let i = 1; i <= 100; i++) {
setTimeout(() => send(i), 0);
}
for await (const y of iterator) {
console.log("y:", y);
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment