Course contentsShow
← Node.js
Lesson 240 of 1,9803. Asynchronous Patterns and Flow ControlFree lesson

Managing Event Priority

You will implement a tiered event dispatcher to ensure high-priority system events are processed before background tasks.

In this lesson, you will learn how to build a tiered event dispatcher to ensure critical system alerts jump to the front of the line, even when background tasks are flooding your event loop.

The Problem of First-Come, First-Served

By default, standard EventEmitter instances process listeners in the order they were attached. If you have a low-priority logging task that takes a long time, and then a high-priority "system shutdown" event occurs, the shutdown event sits behind the logger in the execution queue. This can lead to system lag or delayed reactions to critical errors.

Tiered Event Dispatching

To manage priority, we replace the single-queue approach with a tiered architecture. Instead of emitting events directly, we route them through an internal structure that categorizes them into different "queues."

Here is how you can implement a simple tiered dispatcher:

class PriorityEmitter {
  constructor() {
    this.queues = { high: [], low: [] };
  }

  on(priority, callback) {
    this.queues[priority].push(callback);
  }

  async emit(priority, data) {
    // High priority events process immediately
    if (priority === 'high') {
      for (const cb of this.queues.high) await cb(data);
    } else {
      // Low priority events wait for high priority to clear
      setImmediate(async () => {
        for (const cb of this.queues.low) await cb(data);
      });
    }
  }
}

Why This Works

In this pattern, high-priority tasks are executed synchronously within the emit call, ensuring they run as soon as the event is triggered. For low-priority tasks, we use setImmediate(). This shifts the execution to the next check phase of the event loop, effectively "yielding" control back to the loop so that any pending high-priority events have a chance to be processed before the background work resumes.

This prevents background noise from causing "event starvation," where your most important system signals are stuck waiting for trivial tasks to finish. By explicitly controlling the order of operations, you ensure your application remains responsive under pressure.

Key Takeaway: By segregating events into priority-based queues and using setImmediate for non-critical tasks, you prevent background work from blocking time-sensitive system events.