The Observer pattern is very commonly used in JavaScript. Whenever a state change is bound to an event, that state becomes observable through the event. As the name suggests, the functions that are subscribed to an event act as observers and receive notifications whenever the event is triggered or updated.
Let’s understand this design pattern with a simple JavaScript example. Imagine we have two input fields: one accepts a number, and the other displays a progress bar whose width increases based on that number. In this case, the progress bar is an observer of the number input field—it subscribes to the input field’s events and updates whenever the value changes.
To implement this, we first create a JavaScript function where each host maintains its own list of observer functions. These functions are stored in an internal list. We then provide a subscribe method, which adds a new observer function to the list, and an unsubscribe method, which removes an observer from the list.
Finally, we define the fire method. This method accepts the state and an optional object reference. Since we want the event to be accessible to all observer functions, the method loops through the observer list and calls each function, using .call to bind the state to the given object.
const progress=function(){
this.list=[];
this.subscribe=function(fn){
this.list.push(fn);
}
this.unsubscribe=function(fn){
this.list=this.list.filter((item)=>item!=fn);
}
this.fire=function(state,thisobj){
const scope=thisobj||window;
this.list.forEach((item)=>{
item.call(scope,state);
})
}
}
Now, let’s create an instance of our Progress class. We’ll also define a function called applyColor, which will subscribe to this instance. Whenever the input value changes, an event will be fired. This event will trigger the fire() method and pass the new value to all subscribed observers. As a result, the applyColor function will receive the value and update the progress bar accordingly.
const input = document.getElementById("percentInput");
const inputbar = document.getElementById("barInput");
const bar = new progress();
const applycolor = (val) => {
val = Math.max(0, Math.min(100, val)); // clamp 0–100
inputbar.style.background = `linear-gradient(
to right,
#4caf50 ${val}%,
#f0f0f0 ${val}%
)`;
};
bar.subscribe(applycolor);
input.addEventListener("input", () => {
let val = parseInt(input.value) || 0;
bar.fire(val);
});
Top comments (0)