The Observer pattern
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
-
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.
-
Complete the subscription
class EventEmitter { on(event, callback) { this.listeners[event].____(callback); } }Show answer
class EventEmitter { on(event, callback) { this.listeners[event].push(callback); } } -
Match the Observer concepts
- Subject
- Event source
- Observer
- Event listener
- on(event, cb)
- Add subscription
- emit(event, data)
- Emit event