mirror of
https://github.com/captbaritone/webamp.git
synced 2026-01-23 10:15:31 +00:00
52 lines
1.6 KiB
JavaScript
52 lines
1.6 KiB
JavaScript
import invariant from "invariant";
|
|
import TinyQueue from "tinyqueue";
|
|
|
|
// Push promises onto a queue with a priority.
|
|
// Run a given number of jobs in parallel
|
|
// Useful for prioritizing network requests
|
|
export default class LoadQueue {
|
|
constructor({ threads }) {
|
|
// TODO: Consider not running items with zero priority
|
|
// Priority is a function so that items can change their priority between
|
|
// when their priority is evaluated.
|
|
// For example, we might add a track to the playlist and then scroll to/away
|
|
// from it before it gets processed.
|
|
this._queue = new TinyQueue([], (a, b) => a.priority() - b.priority());
|
|
this._availableThreads = threads;
|
|
}
|
|
|
|
push(task, priority) {
|
|
const t = { task, priority };
|
|
this._queue.push(t);
|
|
// Wait until the next event loop to pick a task to run. This way, we can
|
|
// enqueue multiple items in an event loop, and be sure they will be run in
|
|
// priority order.
|
|
setTimeout(() => {
|
|
this._run();
|
|
}, 0);
|
|
return () => {
|
|
// TODO: Could return a boolean representing if the task has already been
|
|
// kicked off.
|
|
this._queue = this._queue.filter((t1) => t1 !== t);
|
|
};
|
|
}
|
|
|
|
_run() {
|
|
while (this._availableThreads > 0) {
|
|
if (this._queue.length === 0) {
|
|
return;
|
|
}
|
|
this._availableThreads--;
|
|
const t = this._queue.pop();
|
|
const promise = t.task();
|
|
invariant(
|
|
typeof promise.then === "function",
|
|
`LoadQueue only supports loading Promises. Got ${promise}`
|
|
);
|
|
promise.then(() => {
|
|
this._availableThreads++;
|
|
this._run();
|
|
});
|
|
}
|
|
}
|
|
}
|