Trusted answers to developer questions

How Observer and Iterator patterns work in RxJS

Free System Design Interview Course

Many candidates are rejected or down-leveled due to poor performance in their System Design Interview. Stand out in System Design Interviews and get hired in 2024 with this popular free course.

Observables are an essential concept in RxJS. The foundation of Observables lies in two software design patterns:

  • The Observer pattern
  • The Iterator pattern

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.

The Observer pattern in RxJS

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}`);
});

The Iterator pattern in RxJS

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:

  • value: the next available value in the sequence
  • done: a flag with value “true” if traversal has been reached to the last value in the sequence, and “false” in every other case.
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 }

RELATED TAGS

rxjs
design pattern

CONTRIBUTOR

Usman Younas
Copyright ©2024 Educative, Inc. All rights reserved
Did you find this helpful?