AsyncQueue.sys.mjs (1866B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /** 6 * Manages a queue of asynchronous tasks, ensuring they are processed sequentially. 7 */ 8 export class AsyncQueue { 9 #processing; 10 #queue; 11 12 constructor() { 13 this.#queue = []; 14 this.#processing = false; 15 } 16 17 /** 18 * Dequeue a task. 19 * 20 * @returns {Promise} 21 * The wrapped task appearing as first item in the queue. 22 */ 23 #dequeue() { 24 return this.#queue.shift(); 25 } 26 27 /** 28 * Dequeue and try to process all the queued tasks. 29 * 30 * @returns {Promise<undefined>} 31 * Promise that resolves when processing the queue is done. 32 */ 33 async #processQueue() { 34 // The queue is already processed or no tasks queued up. 35 if (this.#processing || this.#queue.length === 0) { 36 return; 37 } 38 39 this.#processing = true; 40 41 while (this.#queue.length) { 42 const wrappedTask = this.#dequeue(); 43 await wrappedTask(); 44 } 45 46 this.#processing = false; 47 } 48 49 /** 50 * Enqueue a task. 51 * 52 * @param {Function} task 53 * The task to queue. 54 * 55 * @returns {Promise<object>} 56 * Promise that resolves when the task is completed, with the resolved 57 * value being the result of the task. 58 */ 59 enqueue(task) { 60 const onTaskExecuted = new Promise((resolve, reject) => { 61 // Wrap the task in a function that will resolve or reject the Promise. 62 const wrappedTask = async () => { 63 try { 64 const result = await task(); 65 resolve(result); 66 } catch (error) { 67 reject(error); 68 } 69 }; 70 71 // Add the wrapped task to the queue 72 this.#queue.push(wrappedTask); 73 this.#processQueue(); 74 }); 75 76 return onTaskExecuted; 77 } 78 }