stacker.news/lib/task-queue.js

55 lines
1.6 KiB
JavaScript
Raw Normal View History

/**
* Create a queue to run tasks sequentially
* @returns {Object} - the queue
* @returns {function} enqueue - Function to add a task to the queue
* @returns {function} lock - Function to lock the queue
* @returns {function} wait - Function to wait for the queue to be empty
*/
export default function createTaskQueue () {
const queue = {
queue: Promise.resolve(),
/**
* Enqueue a task to be run sequentially
* @param {function} fn - The task function to be enqueued
* @returns {Promise} - A promise that resolves with the result of the task function
*/
enqueue (fn) {
return new Promise((resolve, reject) => {
queue.queue = queue.queue.then(async () => {
try {
resolve(await fn())
} catch (e) {
reject(e)
}
})
})
},
/**
* Lock the queue so that it can't move forward until unlocked
* @param {boolean} [wait=true] - Whether to wait for the lock to be acquired
* @returns {Promise<function>} - A promise that resolves with the unlock function
*/
async lock (wait = true) {
let unlock
const lock = new Promise((resolve) => { unlock = resolve })
const locking = new Promise((resolve) => {
queue.queue = queue.queue.then(() => {
resolve()
return lock
})
})
if (wait) await locking
return unlock
},
/**
* Wait for the queue to be empty
* @returns {Promise} - A promise that resolves when the queue is empty
*/
async wait () {
return queue.queue
}
}
return queue
}