liveBook · Manning

Observable

As explained in Get Programming with JavaScript Next: New features of ECMAScript 2015, 2016, and beyond

An observable is a source of asynchronous values that can be subscribed to and can signal start, next, error, and complete notifications to an observer.

Imagine a clock widget that needs a fresh time every second. A promise settles once; an observable can keep sending values. An observable is an object whose stream of values you subscribe to—useful when new data arrives over time, as with a clock or events pushed through a WebSocket. section 33.0

Create one with `new Observable(observer => { ... })`. The observer may provide `start` for the subscription’s one-time start, `next` for each value, `error` for an error, and `complete` when the stream finishes. All four methods are optional. section 33.1

const currentTime$ = new Observable(observer => {
  const interval = setInterval(() => {
    const currentTime = new Date();
    observer.next(currentTime);
  }, 1000);

  return () => clearInterval(interval);           1
});
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":4,\"ch\":5},{\"line\":4,\"ch\":6}],[{\"line\":6,\"ch\":50},{\"line\":6,\"ch\":51}]]"}
!@%STYLE%@!

For a clock, an interval calls `observer.next(new Date())` every second. The returned cleanup function clears that interval when the subscription is unsubscribed—for example, after the widget closes. section 33.1

`Observable.of(1, 2, 3)` creates a stream from the supplied values; `Observable.from(new Set([1, 2, 3]))` creates one from an iterable. A trailing `$` in a variable name is a convention for identifying an observable, not a requirement. section 33.1

Show only changes

A clock’s date stream can be mapped to hour-and-minute strings, then passed through `distinct()` so repeated strings do not notify the widget. Each combinator produces a new observable; it does not change the original. Combinators such as these come from libraries, not the Observable spec itself. section 33.2

function filter (obs$, fn) {                               1
  return new Observable(observer => obs$.subscribe({       2
    next(val) {
      if (fn(val)) observer.next(val);                     3
    }
  }));
}
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":59},{\"line\":0,\"ch\":60}],[{\"line\":1,\"ch\":59},{\"line\":1,\"ch\":60}],[{\"line\":3,\"ch\":59},{\"line\":3,\"ch\":60}]]"}
!@%STYLE%@!

A custom `filter` combinator accepts a source observable and a test, subscribes to the source, and forwards passing values through a new observable. This short version forwards `next` values but omits `error` and `complete`. section 33.3

Try composing `collect`, which emits the values seen so far as an array, with `sum`, which sums each array. Applied to `Observable.of(1, 2, 3, 4)`, the result should emit 1, 3, 6, and 10. section 33.4

How Get Programming with JavaScript Next: New features of ECMAScript 2015, 2016, and beyond covers it

How deep it goes
Walks through construction, notifications, cleanup, and composition, then sketches a filter combinator without forwarding error or completion.
Examples
Uses a ticking clock, an iterable converted to a stream, odd-number filtering, and a cumulative-sum exercise.
What it assumes
Assumes familiarity with JavaScript callbacks and intervals while defining observers and their notifications.
What you can do after
Build it from scratch with the Observable constructor, subscribe and unsubscribe, and compose or write combinators.
How it connects
Connects observables to promises, WebSockets, subscriptions, iterables, and higher-order combinators.

Also explained in

Compare how 5 books explain observable →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Get Programming with JavaScript Next: New features of ECMAScript 2015, 2016, and beyond. The section links point to the parts of the book it draws on.