Observables are an essential concept in RxJS. The foundation of Observables lies in two software design patterns:
Ideally, RxJS combines the Observer pattern with the Iterator pattern and functional programming with collections to fill the ideal way of managing sequences of events. So, it is not wrong to say that Observables in RxJS are a merger of observer and iterator software patterns.
In general, the Observer software pattern is when an object maintains a list of its dependents and automatically notifies them of any state changes by calling one of their functions.
In RxJS, an object called Subject
keeps a list of Listeners subscribed to it. Whenever the Subject
state changes, it notifies all of its Listeners by calling a Listener’s update()
function.
A simple implementation of the Observer pattern is as follows:
const Subject = () => {
let listeners = [];
let count = 0;
setDuration(() => {
count += 1;
listeners.forEach(listener => listener(count));
}, 1000);
return {
subscribe: listener => listeners.push(listener)
};
};
const sbj = Subject();
sbj.subscribe(count => {
console.log(`Listener observed # is${count}`);
});
In the Iterator pattern, an iterator is implemented to traverse a container and access the elements stored in the container. The iterator pattern decouples algorithms from containers.
Like other implementations of the iterator pattern, JavaScript iterators don’t have a hasNext()
method. Instead, an object with two properties is returned every time. These two properties are:
const Iterator = seq => {
let token = -1;
const last = seq.length - 1;
return {
next: () => {
const val = seq[Math.min((token += 1), last)];
const done = val === seq[last];
return { val, done };
}
};
};
const itr = Iterator([10, 20, 30]);
itr.next(); // => { value: 10, done: false }
itr.next(); // => { value: 20, done: false }
itr.next(); // => { value: 30, done: true }