Building an async task queue
And pub-sub
architecture in JS can be a great way to leverage Javascript concurrency model and performance.
1. Async Task Queue:
For an async task queue, you can use the async
library, but let's build a simple one using native JavaScript promises and setTimeout
.
Queue Implementation
class TaskQueue {
constructor(concurrency) {
this.queue = [];
this.concurrency = concurrency;
this.running = 0;
}
async runTask(task) {
if (this.running >= this.concurrency) {
await new Promise(resolve => this.queue.push(resolve));
}
this.running++;
try {
await task();
} finally {
this.running--;
if (this.queue.length > 0) {
this.queue.shift()();
}
}
}
addTask(task) {
return this.runTask(task);
}
}
// Usage example
const queue = new TaskQueue(2);
const createTask = (i) => () => new Promise((resolve) => {
setTimeout(() => {
console.log(`Task ${i} completed`);
resolve();
}, 1000);
});
for (let i = 1; i <= 5; i++) {
queue.addTask(createTask(i));
}
TaskQueue Class:
-
Constructor
: Initializes the task queue with a maximum concurrency (this.concurrency
) and a running count (this.running
). -
runTask(task)
: Handles executing tasks. If the number of currently running tasks reaches the concurrency limit, it waits (using a promise) until a slot becomes available. Once a task starts, it increments the running counter. After completing a task, it decrements the counter and checks if there are queued tasks waiting to be executed. -
addTask(task)
: Adds a new task to the queue.
Usage Example:
-
createTask(i)
: A function that returns a task. Each task is a promise that resolves after 1 second and logs a message. -
for Loop
: Adds multiple tasks to the queue. The queue will process tasks based on the concurrency limit.
2. Pub-Sub Architecture:
A basic pub-sub system can be built using simple JavaScript objects. Subscribers register themselves to topics, and publishers send messages to these topics.
Pub-Sub Implementation
class PubSub {
constructor() {
this.topics = {};
}
subscribe(topic, listener) {
if (!this.topics[topic]) {
this.topics[topic] = [];
}
this.topics[topic].push(listener);
}
publish(topic, message) {
if (this.topics[topic]) {
this.topics[topic].forEach(listener => listener(message));
}
}
}
// Usage example
const pubsub = new PubSub();
pubsub.subscribe('news', (message) => {
console.log(`Received message: ${message}`);
});
pubsub.publish('news', 'Hello World!');
pubsub.publish('news', 'Another message!');
PubSub Class:
Constructor
: Initializes an empty object to hold topics and their associated listeners.
subscribe(topic, listener)
: Adds a listener function to a topic. If the topic doesn’t exist, it creates a new array for it.
publish(topic, message)
: Iterates over all listeners for the given topic and calls them with the provided message.
Usage Example:
-
pubsub.subscribe('news', (message) => {...})
: Subscribes to the 'news' topic with a listener that logs received messages. -
pubsub.publish('news', 'Hello World!')
: Publishes a message to the 'news' topic. All subscribed listeners will be notified with this message.
Summary
- Async Task Queue: Managed with native JavaScript promises and concurrency control.
- Pub-Sub Architecture: Uses plain JavaScript objects to manage topics and listeners.
Top comments (0)