This question was asked in Uber's frontend interview and Swiggy's frontend interview.
Create a simple Observable class that implements the observer pattern. The class should:
const observable = new Observable();
// Subscribe to changes
const subscription = observable.subscribe(data => {
console.log('Received:', data);
});
// Notify subscribers
observable.notify('Hello!'); // logs: "Received: Hello!"
// Unsubscribe
subscription.unsubscribe();
// No longer logs anything
observable.notify('Hello again!');
It is the variation of the pub-sub - 1 and implements the observer design pattern.
If you follow the example, we have to create a new instance of Observable which will return two methods subscribe(callback) and notify(msg)
subscribe(callback) returns another method unsubscribe() that removes the current callback.
When the notify(msg) is invoked, the message is passed to the callback function that can accept it as argument and then render it.
function Observable() {
this.observers = [];
this.subscribe = function(callback) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function');
}
// Convert to object for easy access
const observer = { callback: callback };
this.observers.push(observer);
// Return subscription object with unsubscribe method using arrow function
return {
unsubscribe: () => {
const index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
}
}
};
};
// Can accept any number of arguments
this.notify = function(...data) {
this.observers.forEach(function(observer) {
try {
// Pass the arguments to callback
observer.callback(...data);
} catch (error) {
console.error('Error in observer callback:', error);
}
});
};
// Additional utility methods
this.hasObservers = function() {
return this.observers.length > 0;
};
this.getObserverCount = function() {
return this.observers.length;
};
this.clear = function() {
this.observers = [];
};
}
const observable = new Observable();
// Multiple subscribers
const sub1 = observable.subscribe(function(data) {
console.log('Sub1:', data);
});
const sub2 = observable.subscribe(function(data) {
console.log('Sub2:', data);
});
const sub3 = observable.subscribe(function(data) {
console.log('Sub3:', data);
});
console.log('Observer count:', observable.getObserverCount()); // 3
observable.notify('Broadcast message');
// Logs:
// Sub1: Broadcast message
// Sub2: Broadcast message
// Sub3: Broadcast message
// Unsubscribe one
sub2.unsubscribe();
observable.notify('Another message');
// Logs:
// Sub1: Another message
// Sub3: Another message
// Clear all observers
observable.clear();
observable.notify('No one listening'); // Nothing logged