Priority-Based Event Dispatching in JavaScript/TypeScript: A 2026 Guide

Master priority-based event dispatching in JavaScript/TypeScript. Learn to handle priority listeners, stop propagation, and create async events seamlessly.

Priority-Based Event Dispatching in JavaScript/TypeScript: A 2026 Guide

Priority-Based Event Dispatching in JavaScript/TypeScript: A 2026 Guide

Building robust applications that run both in the browser and Node.js often requires a sophisticated event system. This tutorial will guide you through implementing a priority-based event dispatching system in JavaScript and TypeScript. You'll learn how to handle priority-based listener execution, stoppable propagation, and both asynchronous and synchronous listeners in a type-safe manner.

Key Takeaways

  • Implement a priority-based event system in JavaScript/TypeScript.
  • Create type-safe events for both browser and Node.js environments.
  • Learn to stop event propagation effectively.
  • Develop both synchronous and asynchronous event listeners.

Introduction

Event-driven programming is a powerful paradigm, especially for applications needing to execute code in response to user actions, server requests, or other asynchronous events. In modern JavaScript/TypeScript applications, it's vital to have an event system that can prioritize certain listeners over others, stop event propagation when necessary, and support asynchronous operations. This capability ensures that your application remains responsive and behaves as expected in complex scenarios.

In this tutorial, we will build an event dispatching system that supports:

  • Priority-based execution of event listeners.
  • Stoppable propagation, where a listener can prevent subsequent listeners from executing.
  • Support for both fire-and-forget and awaitable sequential execution of asynchronous listeners.
  • Type-safe event handling using TypeScript.

By the end of this guide, you will have a complete understanding of how to implement these features, ensuring your application can handle events efficiently and effectively.

Prerequisites

  • Basic understanding of JavaScript and TypeScript.
  • Familiarity with asynchronous programming concepts in JavaScript.
  • Node.js and npm installed on your system.
  • A text editor or IDE, such as Visual Studio Code.

Step 1: Setting Up Your Project

First, let's set up a new Node.js project with TypeScript. Open your terminal and run the following commands:

mkdir event-dispatcher && cd event-dispatcher
npm init -y
npm install typescript --save-dev
npx tsc --init

This sequence of commands will create a new directory, initialize a Node.js project, and set up TypeScript.

Step 2: Defining the Event System Interface

We will start by defining an interface for our event system. Create a new file named EventSystem.ts and add the following code:

interface EventListener {
  priority: number;
  callback: (...args: any[]) => void | Promise;
}

interface EventSystem {
  on(event: string, listener: EventListener): void;
  off(event: string, listener: EventListener): void;
  emit(event: string, ...args: any[]): Promise;
}

These interfaces define the basic structure of our event system. Each listener has a priority and a callback function that can handle events synchronously or asynchronously.

Step 3: Implementing the Event Dispatcher

Now, let's implement the event dispatcher that will manage our events. Add the following code to EventSystem.ts:

class EventDispatcher implements EventSystem {
  private listeners: Map = new Map();

  public on(event: string, listener: EventListener): void {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event)!.push(listener);
    this.listeners.get(event)!.sort((a, b) => b.priority - a.priority);
  }

  public off(event: string, listener: EventListener): void {
    const listeners = this.listeners.get(event);
    if (listeners) {
      this.listeners.set(event, listeners.filter(l => l !== listener));
    }
  }

  public async emit(event: string, ...args: any[]): Promise {
    const listeners = this.listeners.get(event);
    if (listeners) {
      for (const listener of listeners) {
        await listener.callback(...args);
      }
    }
  }
}

This implementation includes methods to add and remove listeners, as well as emit events. Listeners are sorted by priority to ensure the correct execution order.

Step 4: Handling Event Propagation and Async Execution

We need to add functionality to stop event propagation and handle asynchronous execution. Modify the emit method as follows:

public async emit(event: string, ...args: any[]): Promise {
  const listeners = this.listeners.get(event);
  if (listeners) {
    for (const listener of listeners) {
      const result = await listener.callback(...args);
      if (result === false) {
        break; // Stop propagation if the listener returns false
      }
    }
  }
}

In this updated method, if a listener's callback returns false, it will stop further propagation of the event. This allows a listener to effectively cancel the event for subsequent listeners.

Common Errors/Troubleshooting

  • Listeners Not Executing: Ensure listeners are added with the correct event name and priority.
  • Asynchronous Listeners Failing: Check that your listeners return a Promise and handle async/await properly.
  • Event Propagation Not Stopping: Verify that the listener callback returns false to stop propagation.

Conclusion

By following this guide, you've implemented a robust priority-based event dispatching system in JavaScript/TypeScript that works seamlessly across browser and Node.js environments. This system supports type-safe events, priority-based listener execution, stoppable propagation, and asynchronous operations — all critical components for building responsive applications in 2026.

Frequently Asked Questions

What is priority-based event dispatching?

Priority-based event dispatching allows event listeners to be executed in a specific order based on their priority level, ensuring that critical listeners run first.

How can I stop event propagation in this system?

To stop event propagation, a listener should return false. This will prevent subsequent listeners from being executed.

Can I use this system in both browser and Node.js environments?

Yes, this system is designed to be environment-agnostic, working seamlessly in both browser and Node.js settings.