CodeBlanks Logo Icon CodeBlanks

The Observer pattern

JavaScript course · Expert · Lesson 4/63

Learn the pattern where a subject notifies multiple observers.

The Observer pattern

The Observer pattern lets a subject notify multiple observers. When state changes, the subject emits an event to all subscribers.

JavaScript events follow this model: addEventListener subscribes, and the browser calls subscribers when the event fires.

We can apply the same model by writing our own EventEmitter class: on subscribes, emit emits.

EventEmitter implementation

The EventEmitter class holds a listeners object mapping event names to arrays. on(event, callback) pushes the callback onto the matching array.

emit(event, data) then calls every subscribed callback with data in turn.

emitter.on('login', cb);
emitter.emit('login', user);

This structure underlies most modern libraries.

Exercise EventEmitter class

Declare an EventEmitter class. Its constructor sets this.listeners to an empty object {}. The on(event, callback) method pushes callback onto the this.listeners[event] array (create an empty array first if needed). The emit(event, data) method calls every subscribed callback with data.

Show example solution
Start with class EventEmitter, set this.listeners = {} in the constructor, in on(event, callback) call this.listeners[event].push(callback), in emit(event, data) call subscribers with cb(data).
Example solution:
class EventEmitter {
  constructor() {
    this.listeners = {};
  }
  on(event, callback) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(callback);
  }
  emit(event, data) {
    if (this.listeners[event]) {
      for (const cb of this.listeners[event]) {
        cb(data);
      }
    }
  }
}

Test yourself

  1. What does 'emit' do in the Observer pattern?

    • Create a new object
    • Clear the subscriber list
    • Hide the class
    • Notify all subscribers of an event
    Show answer

    Notify all subscribers of an event — Correct! emit calls every registered callback with the event data.

  2. Complete the subscription

    class EventEmitter {
      on(event, callback) {
        this.listeners[event].____(callback);
      }
    }
    Show answer
    class EventEmitter {
      on(event, callback) {
        this.listeners[event].push(callback);
      }
    }
  3. Match the Observer concepts

    Subject
    Event source
    Observer
    Event listener
    on(event, cb)
    Add subscription
    emit(event, data)
    Emit event

All lessons in Expert