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

The Observer Pattern in Async Logic

You will implement the Observer pattern to notify multiple disparate services of specific system-wide changes.

In this lesson, you will learn how to decouple your system’s core logic from peripheral services by using the Observer pattern to broadcast asynchronous state changes.

The Core Concept

When building complex Node.js applications, you often encounter a scenario where one "Subject" (like a User Account service) needs to notify several disparate "Observers" (like an Emailer, an Audit Logger, and an Analytics dashboard) whenever a significant action occurs.

Instead of writing a function that explicitly calls all three services, you create a central hub that tracks these observers. When an event triggers, the Subject iterates through its registered observers and invokes their update methods. Because we are in Node.js, we treat these notifications as asynchronous tasks to ensure that a slow logger doesn't block the main account update flow.

Implementation Illustration

Think of the Subject as a radio transmitter and the Observers as radios tuned to a specific frequency.

class SystemObserver {
  constructor() {
    this.observers = [];
  }

  subscribe(fn) {
    this.observers.push(fn);
  }

  // Notify observers asynchronously to prevent blocking
  async notify(data) {
    const tasks = this.observers.map(observer => observer(data));
    await Promise.allSettled(tasks);
  }
}

// Usage
const userEvents = new SystemObserver();

userEvents.subscribe(async (user) => console.log(`Email sent to ${user.email}`));
userEvents.subscribe(async (user) => console.log(`Audit log updated for ${user.id}`));

// Triggering the flow
await userEvents.notify({ id: 1, email: 'student@example.com' });

Why This Matters

By using this pattern, your core code doesn't need to know what happens when a user signs up. It only knows that it must announce the event. This is powerful because you can add a new observer—like a "Slack Notification" service—without touching the code that creates the user. You are keeping your modules focused and independent, which is vital for maintaining clean asynchronous flows as your application grows.

Key Takeaway: The Observer pattern allows you to broadcast system changes to multiple independent services asynchronously, ensuring your core logic remains clean and decoupled from the side effects it triggers.