gen-q
v0.1.6
Published
An efficient queue implementation for JavaScript
Maintainers
Readme
gen-q
Social Media Photo by Meizhi Lang on Unsplash
Highly inspired by Refillable Generators post (now 401 🤷), this module uses a modern JS approach through a class that doesn't need to provide "error prone" utilities around, as explained in my reply.
import Queue from 'https://esm.run/gen-q';
// Keep waiting for pushes forever.
// It exits on an explicit queue reset: splice(0).
async function test(items) {
for await (const item of items)
console.log(item);
console.log('done');
}
const numbers = new Queue(1, 2, 3);
test(numbers);
// It fails if it was not consumed or reset.
try {
await test(numbers);
console.assert(false, 'should have thrown an error');
}
catch {}
// Exit the test after 3 seconds.
setTimeout(() => {
numbers.splice(0);
}, 3000);
setTimeout((...args) => {
// Nobody will see these items:
// they are pushed, then synchronously removed via splice.
numbers.push(...args);
// Drop all items from the queue. Like map and other
// methods, it returns a new Queue.
console.assert(numbers.splice(0) instanceof Queue);
// Push and then loop again.
setTimeout(async () => {
numbers.push(...args);
await test(numbers);
// This will exit in a second.
}, 1000);
}, 1000, 4, 5, 6);
// output
// 1
// 2
// 3
// done
// 4
// 5
// 6
// doneIf you never want the async function to exit, restart queue iteration after each reset:
// Keep waiting for pushes forever.
// splice(0) exits only the current queue iteration.
async function test(items) {
while (true) {
for await (const item of items)
console.log(item);
}
}
const numbers = new Queue(1, 2, 3);
test(numbers);
// will never exitThis pattern can be used to simulate or create an event loop via JS micro tasks.
Introducing gen-q/utils
The forever utility provides the same restart behavior without writing the outer loop manually:
import Queue from 'https://esm.run/gen-q';
import { forever } from 'https://esm.run/gen-q/utils';
const numbers = new Queue(1, 2, 3);
// This one will never exit, and it owns the queue.
(async function test(items) {
for await (const item of forever(items))
console.log(item);
}(numbers));
// Any attempt to loop over the queue will fail,
// but the anonymous loop will keep going.
// Reset the current queue iteration after 3 seconds.
setTimeout(() => {
numbers.splice(0);
}, 3000);
setTimeout((...args) => {
// Nobody will see these items:
// they are pushed, then synchronously removed via splice.
numbers.push(...args);
// Drop all items from the queue. Like map and other
// methods, it returns a new Queue.
console.assert(numbers.splice(0) instanceof Queue);
// Push later; `test` is still running.
setTimeout(async () => {
numbers.push(...args);
}, 1000);
}, 1000, 4, 5, 6);
// output
// 1
// 2
// 3
// 4
// 5
// 6