@reactivex/rxjs
Version:
Reactive Extensions for modern JavaScript
704 lines (675 loc) • 89.8 kB
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../">
<title data-ice="title">Overview</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<script data-ice="userScript" src="user/script/0-Rx.js"></script>
<script data-ice="userScript" src="user/script/1-devtools-welcome.js"></script>
<script data-ice="userScript" src="user/script/2-custom-manual-styles.js"></script>
<script data-ice="userScript" src="user/script/3-decision-tree-widget.min.js"></script>
<script data-ice="userScript" src="user/script/4-theme-toggler.js"></script>
<link data-ice="userStyle" rel="stylesheet" href="user/css/0-main.css">
</head>
<body class="layout-container manual-root" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="./manual/index.html" data-ice="manualHeaderLink">Manual</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<a href="test.html" data-ice="testLink">Test</a>
<a data-ice="repoURL" href="https://github.com/ReactiveX/RxJS" class="repo-url-github">Repository</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
</header>
<nav class="navigation" data-ice="nav"><div class="manual-toc-root">
<div data-ice="manual" data-toc-name="overview">
<h1 class="manual-toc-title"><a href="manual/overview.html" data-ice="title">Overview</a></h1>
<ul class="manual-toc">
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/overview.html#introduction" data-ice="link">Introduction</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#first-examples" data-ice="link">First examples</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#purity" data-ice="link">Purity</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#flow" data-ice="link">Flow</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#values" data-ice="link">Values</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/overview.html#observable" data-ice="link">Observable</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#pull-versus-push" data-ice="link">Pull versus Push</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#observables-as-generalizations-of-functions" data-ice="link">Observables as generalizations of functions</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#anatomy-of-an-observable" data-ice="link">Anatomy of an Observable</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#creating-observables" data-ice="link">Creating Observables</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#subscribing-to-observables" data-ice="link">Subscribing to Observables</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#executing-observables" data-ice="link">Executing Observables</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#disposing-observable-executions" data-ice="link">Disposing Observable Executions</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/overview.html#observer" data-ice="link">Observer</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/overview.html#subscription" data-ice="link">Subscription</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/overview.html#subject" data-ice="link">Subject</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#multicasted-observables" data-ice="link">Multicasted Observables</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#reference-counting" data-ice="link">Reference counting</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#behaviorsubject" data-ice="link">BehaviorSubject</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#replaysubject" data-ice="link">ReplaySubject</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#asyncsubject" data-ice="link">AsyncSubject</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/overview.html#operators" data-ice="link">Operators</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#what-are-operators-" data-ice="link">What are operators?</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#instance-operators-versus-static-operators" data-ice="link">Instance operators versus static operators</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#marble-diagrams" data-ice="link">Marble diagrams</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#choose-an-operator" data-ice="link">Choose an operator</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#categories-of-operators" data-ice="link">Categories of operators</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#creation-operators" data-ice="link">Creation Operators</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#transformation-operators" data-ice="link">Transformation Operators</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#filtering-operators" data-ice="link">Filtering Operators</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#combination-operators" data-ice="link">Combination Operators</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#multicasting-operators" data-ice="link">Multicasting Operators</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#error-handling-operators" data-ice="link">Error Handling Operators</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#utility-operators" data-ice="link">Utility Operators</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#conditional-and-boolean-operators" data-ice="link">Conditional and Boolean Operators</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/overview.html#mathematical-and-aggregate-operators" data-ice="link">Mathematical and Aggregate Operators</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/overview.html#scheduler" data-ice="link">Scheduler</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#scheduler-types" data-ice="link">Scheduler Types</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/overview.html#using-schedulers" data-ice="link">Using Schedulers</a></li>
</ul>
</div>
<div data-ice="manual" data-toc-name="installation">
<h1 class="manual-toc-title"><a href="manual/installation.html" data-ice="title">Installation</a></h1>
<ul class="manual-toc">
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/installation.html#es6-via-npm" data-ice="link">ES6 via npm</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/installation.html#commonjs-via-npm" data-ice="link">CommonJS via npm</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/installation.html#commonjs-with-typescript" data-ice="link">CommonJS with TypeScript</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/installation.html#all-module-types-cjs-es6-amd-typescript-via-npm" data-ice="link">All Module Types (CJS/ES6/AMD/TypeScript) via npm</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/installation.html#cdn" data-ice="link">CDN</a></li>
</ul>
</div>
<div data-ice="manual" data-toc-name="tutorial">
<h1 class="manual-toc-title"><a href="manual/tutorial.html" data-ice="title">Tutorial</a></h1>
<ul class="manual-toc">
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/tutorial.html#the-basics" data-ice="link">The basics</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/tutorial.html#converting-to-observables" data-ice="link">Converting to observables</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/tutorial.html#creating-observables" data-ice="link">Creating observables</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/tutorial.html#controlling-the-flow" data-ice="link">Controlling the flow</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/tutorial.html#producing-values" data-ice="link">Producing values</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/tutorial.html#creating-applications" data-ice="link">Creating applications</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/tutorial.html#state-stores" data-ice="link">State stores</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/tutorial.html#immutable-js" data-ice="link">Immutable JS</a></li>
<li data-ice="manualNav" class="indent-h3"><span class="manual-dot"></span><a href="manual/tutorial.html#react" data-ice="link">React</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/tutorial.html#external-references" data-ice="link">External References</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/tutorial.html#tutorials" data-ice="link">Tutorials</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/tutorial.html#books" data-ice="link">Books</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/tutorial.html#videos" data-ice="link">Videos</a></li>
<li data-ice="manualNav" class="indent-h2"><span class="manual-dot"></span><a href="manual/tutorial.html#presentations" data-ice="link">Presentations</a></li>
</ul>
</div>
<div data-ice="manual" data-toc-name="reference">
<h1 class="manual-toc-title"><a href="identifiers.html" data-ice="title">Reference</a></h1>
<ul class="manual-toc">
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="identifiers.html#variable" data-ice="link">Variable</a></li>
<li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="identifiers.html#typedef" data-ice="link">Typedef</a></li>
</ul>
</div>
</div>
</nav>
<div class="content" data-ice="content"><div class="github-markdown">
<div class="manual-breadcrumb-list">
<a href="./manual/./index.html">Manual</a>
<span>»</span>
<span data-ice="title">Overview</span>
</div>
<div data-ice="content"><h1 id="introduction">Introduction</h1>
<p>RxJS is a library for composing asynchronous and event-based programs by using observable sequences. It provides one core type, the <a href="./manual/./overview.html#observable">Observable</a>, satellite types (Observer, Schedulers, Subjects) and operators inspired by <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.6">Array#extras</a> (map, filter, reduce, every, etc) to allow handling asynchronous events as collections.</p>
<p><span class="informal">Think of RxJS as Lodash for events.</span></p>
<p>ReactiveX combines the <a href="https://en.wikipedia.org/wiki/Observer_pattern">Observer pattern</a> with the <a href="https://en.wikipedia.org/wiki/Iterator_pattern">Iterator pattern</a> and <a href="http://martinfowler.com/articles/collection-pipeline/#NestedOperatorExpressions">functional programming with collections</a> to fill the need for an ideal way of managing sequences of events.</p>
<p>The essential concepts in RxJS which solve async event management are:</p>
<ul>
<li><strong>Observable:</strong> represents the idea of an invokable collection of future values or events.</li>
<li><strong>Observer:</strong> is a collection of callbacks that knows how to listen to values delivered by the Observable.</li>
<li><strong>Subscription:</strong> represents the execution of an Observable, is primarily useful for cancelling the execution.</li>
<li><strong>Operators:</strong> are pure functions that enable a functional programming style of dealing with collections with operations like <code>map</code>, <code>filter</code>, <code>concat</code>, <code>flatMap</code>, etc.</li>
<li><strong>Subject:</strong> is the equivalent to an EventEmitter, and the only way of multicasting a value or event to multiple Observers.</li>
<li><strong>Schedulers:</strong> are centralized dispatchers to control concurrency, allowing us to coordinate when computation happens on e.g. <code>setTimeout</code> or <code>requestAnimationFrame</code> or others.</li>
</ul>
<h2 id="first-examples">First examples</h2>
<p>Normally you register event listeners.</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var button = document.querySelector('button');
button.addEventListener('click', () => console.log('Clicked!'));</code>
</code></pre>
<p>Using RxJS you create an observable instead.</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.subscribe(() => console.log('Clicked!'));</code>
</code></pre>
<h3 id="purity">Purity</h3>
<p>What makes RxJS powerful is its ability to produce values using pure functions. That means your code is less prone for errors.</p>
<p>Normally you would create an impure function, where other
pieces of your code can mess up your state.</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var count = 0;
var button = document.querySelector('button');
button.addEventListener('click', () => console.log(`Clicked ${++count} times`));</code>
</code></pre>
<p>Using RxJS you isolate the state.</p>
<pre><code class="lang-Js"><code class="source-code prettyprint">var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.scan(count => count + 1, 0)
.subscribe(count => console.log(`Clicked ${count} times`));</code>
</code></pre>
<p>The <strong>scan</strong> operator works just like <strong>reduce</strong> for arrays. It takes a value which is exposed to a callback. The returned value of the callback will then become the next value exposed the next time the callback runs.</p>
<h3 id="flow">Flow</h3>
<p>RxJS has a whole range of operators that helps you control how the events flow through your observables.</p>
<p>This is how you would allow at most one click per second, with plain JavaScript:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
var button = document.querySelector('button');
button.addEventListener('click', () => {
if (Date.now() - lastClick >= rate) {
console.log(`Clicked ${++count} times`);
lastClick = Date.now();
}
});</code>
</code></pre>
<p>With RxJS:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.throttleTime(1000)
.scan(count => count + 1, 0)
.subscribe(count => console.log(`Clicked ${count} times`));</code>
</code></pre>
<p>Other flow control operators are <a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-filter"><strong>filter</strong></a>, <a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-delay"><strong>delay</strong></a>, <a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-debounceTime"><strong>debounceTime</strong></a>, <a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-take"><strong>take</strong></a>, <a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-takeUntil"><strong>takeUntil</strong></a>, <a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-distinct"><strong>distinct</strong></a>, <a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-distinctUntilChanged"><strong>distinctUntilChanged</strong></a> etc.</p>
<h3 id="values">Values</h3>
<p>You can transform the values passed through your observables.</p>
<p>Here's how you can add the current mouse x position for every click, in plain JavaScript:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
var button = document.querySelector('button');
button.addEventListener('click', (event) => {
if (Date.now() - lastClick >= rate) {
console.log(++count + event.clientX)
lastClick = Date.now();
}
});</code>
</code></pre>
<p>With RxJS:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.throttleTime(1000)
.map(event => event.clientX)
.scan((count, clientX) => count + clientX, 0)
.subscribe(count => console.log(count));</code>
</code></pre>
<p>Other value producing operators are <a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-pluck"><strong>pluck</strong></a>, <a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-pairwise"><strong>pairwise</strong></a>,
<a href="./manual/../class/es6/Observable.js~Observable.html#instance-method-sample"><strong>sample</strong></a> etc.</p>
<h1 id="observable">Observable</h1>
<p>Observables are lazy Push collections of multiple values. They fill the missing spot in the following table:</p>
<table>
<thead>
<tr>
<th></th>
<th>Single</th>
<th>Multiple</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Pull</strong></td>
<td><a href="https://developer.mozilla.org/en-US/docs/Glossary/Function"><code>Function</code></a></td>
<td><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols">Iterator</a></td>
</tr>
<tr>
<td><strong>Push</strong></td>
<td><a href="https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Promise"><code>Promise</code></a></td>
<td><a href="./manual/../class/es6/Observable.js~Observable.html"><code>Observable</code></a></td>
</tr>
</tbody>
</table>
<p><strong>Example.</strong> The following is an Observable that pushes the values <code>1</code>, <code>2</code>, <code>3</code> immediately (synchronously) when subscribed, and the value <code>4</code> after one second has passed since the subscribe call, then completes:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable = Rx.Observable.create(function (observer) {
observer.next(1);
observer.next(2);
observer.next(3);
setTimeout(() => {
observer.next(4);
observer.complete();
}, 1000);
});</code>
</code></pre>
<p>To invoke the Observable and see these values, we need to <em>subscribe</em> to it:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable = Rx.Observable.create(function (observer) {
observer.next(1);
observer.next(2);
observer.next(3);
setTimeout(() => {
observer.next(4);
observer.complete();
}, 1000);
});
console.log('just before subscribe');
observable.subscribe({
next: x => console.log('got value ' + x),
error: err => console.error('something wrong occurred: ' + err),
complete: () => console.log('done'),
});
console.log('just after subscribe');</code>
</code></pre>
<p>Which executes as such on the console:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">just before subscribe
got value 1
got value 2
got value 3
just after subscribe
got value 4
done</code>
</code></pre>
<h2 id="pull-versus-push">Pull versus Push</h2>
<p><em>Pull</em> and <em>Push</em> are two different protocols how a data <em>Producer</em> can communicate with a data <em>Consumer</em>.</p>
<p><strong>What is Pull?</strong> In Pull systems, the Consumer determines when it receives data from the data Producer. The Producer itself is unaware of when the data will be delivered to the Consumer.</p>
<p>Every JavaScript Function is a Pull system. The function is a Producer of data, and the code that calls the function is consuming it by "pulling" out a <em>single</em> return value from its call.</p>
<p>ES2015 introduced <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*">generator functions and iterators</a> (<code>function*</code>), another type of Pull system. Code that calls <code>iterator.next()</code> is the Consumer, "pulling" out <em>multiple</em> values from the iterator (the Producer).</p>
<table>
<thead>
<tr>
<th></th>
<th>Producer</th>
<th>Consumer</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Pull</strong></td>
<td><strong>Passive:</strong> produces data when requested.</td>
<td><strong>Active:</strong> decides when data is requested.</td>
</tr>
<tr>
<td><strong>Push</strong></td>
<td><strong>Active:</strong> produces data at its own pace.</td>
<td><strong>Passive:</strong> reacts to received data.</td>
</tr>
</tbody>
</table>
<p><strong>What is Push?</strong> In Push systems, the Producer determines when to send data to the Consumer. The Consumer is unaware of when it will receive that data.</p>
<p>Promises are the most common type of Push system in JavaScript today. A Promise (the Producer) delivers a resolved value to registered callbacks (the Consumers), but unlike functions, it is the Promise which is in charge of determining precisely when that value is "pushed" to the callbacks.</p>
<p>RxJS introduces Observables, a new Push system for JavaScript. An Observable is a Producer of multiple values, "pushing" them to Observers (Consumers).</p>
<ul>
<li>A <strong>Function</strong> is a lazily evaluated computation that synchronously returns a single value on invocation.</li>
<li>A <strong>generator</strong> is a lazily evaluated computation that synchronously returns zero to (potentially) infinite values on iteration.</li>
<li>A <strong>Promise</strong> is a computation that may (or may not) eventually return a single value.</li>
<li>An <strong>Observable</strong> is a lazily evaluated computation that can synchronously or asynchronously return zero to (potentially) infinite values from the time it's invoked onwards.</li>
</ul>
<h2 id="observables-as-generalizations-of-functions">Observables as generalizations of functions</h2>
<p>Contrary to popular claims, Observables are not like EventEmitters nor are they like Promises for multiple values. Observables <em>may act</em> like EventEmitters in some cases, namely when they are multicasted using RxJS Subjects, but usually they don't act like EventEmitters.</p>
<p><span class="informal">Observables are like functions with zero arguments, but generalize those to allow multiple values.</span></p>
<p>Consider the following:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">function foo() {
console.log('Hello');
return 42;
}
var x = foo.call(); // same as foo()
console.log(x);
var y = foo.call(); // same as foo()
console.log(y);</code>
</code></pre>
<p>We expect to see as output:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">"Hello"
42
"Hello"
42</code>
</code></pre>
<p>You can write the same behavior above, but with Observables:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var foo = Rx.Observable.create(function (observer) {
console.log('Hello');
observer.next(42);
});
foo.subscribe(function (x) {
console.log(x);
});
foo.subscribe(function (y) {
console.log(y);
});</code>
</code></pre>
<p>And the output is the same:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">"Hello"
42
"Hello"
42</code>
</code></pre>
<p>This happens because both functions and Observables are lazy computations. If you don't call the function, the <code>console.log('Hello')</code> won't happen. Also with Observables, if you don't "call" it (with <code>subscribe</code>), the <code>console.log('Hello')</code> won't happen. Plus, "calling" or "subscribing" is an isolated operation: two function calls trigger two separate side effects, and two Observable subscribes trigger two separate side effects. As opposed to EventEmitters which share the side effects and have eager execution regardless of the existence of subscribers, Observables have no shared execution and are lazy.</p>
<p><span class="informal">Subscribing to an Observable is analogous to calling a Function.</span></p>
<p>Some people claim that Observables are asynchronous. That is not true. If you surround a function call with logs, like this:</p>
<p><!-- skip-example -->
</p>
<pre><code class="lang-js"><code class="source-code prettyprint">console.log('before');
console.log(foo.call());
console.log('after');</code>
</code></pre>
<p>You will see the output:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">"before"
"Hello"
42
"after"</code>
</code></pre>
<p>And this is the same behavior with Observables:</p>
<p><!-- skip-example -->
</p>
<pre><code class="lang-js"><code class="source-code prettyprint">console.log('before');
foo.subscribe(function (x) {
console.log(x);
});
console.log('after');</code>
</code></pre>
<p>And the output is:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">"before"
"Hello"
42
"after"</code>
</code></pre>
<p>Which proves the subscription of <code>foo</code> was entirely synchronous, just like a function.</p>
<p><span class="informal">Observables are able to deliver values either synchronously or asynchronously.</span></p>
<p>What is the difference between an Observable and a function? <strong>Observables can "return" multiple values over time</strong>, something which functions cannot. You can't do this:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">function foo() {
console.log('Hello');
return 42;
return 100; // dead code. will never happen
}</code>
</code></pre>
<p>Functions can only return one value. Observables, however, can do this:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var foo = Rx.Observable.create(function (observer) {
console.log('Hello');
observer.next(42);
observer.next(100); // "return" another value
observer.next(200); // "return" yet another
});
console.log('before');
foo.subscribe(function (x) {
console.log(x);
});
console.log('after');</code>
</code></pre>
<p>With synchronous output:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">"before"
"Hello"
42
100
200
"after"</code>
</code></pre>
<p>But you can also "return" values asynchronously:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var foo = Rx.Observable.create(function (observer) {
console.log('Hello');
observer.next(42);
observer.next(100);
observer.next(200);
setTimeout(() => {
observer.next(300); // happens asynchronously
}, 1000);
});
console.log('before');
foo.subscribe(function (x) {
console.log(x);
});
console.log('after');</code>
</code></pre>
<p>With output:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">"before"
"Hello"
42
100
200
"after"
300</code>
</code></pre>
<p>Conclusion:</p>
<ul>
<li><code>func.call()</code> means "<em>give me one value synchronously</em>"</li>
<li><code>observable.subscribe()</code> means "<em>give me any amount of values, either synchronously or asynchronously</em>"</li>
</ul>
<h2 id="anatomy-of-an-observable">Anatomy of an Observable</h2>
<p>Observables are <strong>created</strong> using <code>Rx.Observable.create</code> or a creation operator, are <strong>subscribed</strong> to with an Observer, <strong>execute</strong> to deliver <code>next</code> / <code>error</code> / <code>complete</code> notifications to the Observer, and their execution may be <strong>disposed</strong>. These four aspects are all encoded in an Observable instance, but some of these aspects are related to other types, like Observer and Subscription.</p>
<p>Core Observable concerns:</p>
<ul>
<li><strong>Creating</strong> Observables</li>
<li><strong>Subscribing</strong> to Observables</li>
<li><strong>Executing</strong> the Observable</li>
<li><strong>Disposing</strong> Observables</li>
</ul>
<h3 id="creating-observables">Creating Observables</h3>
<p><code>Rx.Observable.create</code> is an alias for the <code>Observable</code> constructor, and it takes one argument: the <code>subscribe</code> function.</p>
<p>The following example creates an Observable to emit the string <code>'hi'</code> every second to an Observer.</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable = Rx.Observable.create(function subscribe(observer) {
var id = setInterval(() => {
observer.next('hi')
}, 1000);
});</code>
</code></pre>
<p><span class="informal">Observables can be created with <code>create</code>, but usually we use the so-called <a href="./manual/./overview.html#creation-operators">creation operators</a>, like <code>of</code>, <code>from</code>, <code>interval</code>, etc.</span></p>
<p>In the example above, the <code>subscribe</code> function is the most important piece to describe the Observable. Let's look at what subscribing means.</p>
<h3 id="subscribing-to-observables">Subscribing to Observables</h3>
<p>The Observable <code>observable</code> in the example can be <em>subscribed</em> to, like this:</p>
<p><!-- skip-example -->
</p>
<pre><code class="lang-js"><code class="source-code prettyprint">observable.subscribe(x => console.log(x));</code>
</code></pre>
<p>It is not a coincidence that <code>observable.subscribe</code> and <code>subscribe</code> in <code>Observable.create(function subscribe(observer) {...})</code> have the same name. In the library, they are different, but for practical purposes you can consider them conceptually equal.</p>
<p>This shows how <code>subscribe</code> calls are not shared among multiple Observers of the same Observable. When calling <code>observable.subscribe</code> with an Observer, the function <code>subscribe</code> in <code>Observable.create(function subscribe(observer) {...})</code> is run for that given Observer. Each call to <code>observable.subscribe</code> triggers its own independent setup for that given Observer.</p>
<p><span class="informal">Subscribing to an Observable is like calling a function, providing callbacks where the data will be delivered to.</span></p>
<p>This is drastically different to event handler APIs like <code>addEventListener</code> / <code>removeEventListener</code>. With <code>observable.subscribe</code>, the given Observer is not registered as a listener in the Observable. The Observable does not even maintain a list of attached Observers.</p>
<p>A <code>subscribe</code> call is simply a way to start an "Observable execution" and deliver values or events to an Observer of that execution.</p>
<h3 id="executing-observables">Executing Observables</h3>
<p>The code inside <code>Observable.create(function subscribe(observer) {...})</code> represents an "Observable execution", a lazy computation that only happens for each Observer that subscribes. The execution produces multiple values over time, either synchronously or asynchronously.</p>
<p>There are three types of values an Observable Execution can deliver:</p>
<ul>
<li>"Next" notification: sends a value such as a Number, a String, an Object, etc.</li>
<li>"Error" notification: sends a JavaScript Error or exception.</li>
<li>"Complete" notification: does not send a value.</li>
</ul>
<p>Next notifications are the most important and most common type: they represent actual data being delivered to an Observer. Error and Complete notifications may happen only once during the Observable Execution, and there can only be either one of them.</p>
<p>These constraints are expressed best in the so-called <em>Observable Grammar</em> or <em>Contract</em>, written as a regular expression:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">next*(error|complete)?</code>
</code></pre>
<p><span class="informal">In an Observable Execution, zero to infinite Next notifications may be delivered. If either an Error or Complete notification is delivered, then nothing else can be delivered afterwards.</span></p>
<p>The following is an example of an Observable execution that delivers three Next notifications, then completes:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable = Rx.Observable.create(function subscribe(observer) {
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
});</code>
</code></pre>
<p>Observables strictly adhere to the Observable Contract, so the following code would not deliver the Next notification <code>4</code>:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable = Rx.Observable.create(function subscribe(observer) {
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
observer.next(4); // Is not delivered because it would violate the contract
});</code>
</code></pre>
<p>It is a good idea to wrap any code in <code>subscribe</code> with <code>try</code>/<code>catch</code> block that will deliver an Error notification if it catches an exception:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable = Rx.Observable.create(function subscribe(observer) {
try {
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
} catch (err) {
observer.error(err); // delivers an error if it caught one
}
});</code>
</code></pre>
<h3 id="disposing-observable-executions">Disposing Observable Executions</h3>
<p>Because Observable Executions may be infinite, and it's common for an Observer to want abort execution in finite time, we need an API for canceling an execution. Since each execution is exclusive to one Observer only, once the Observer is done receiving values, it has to have a way to stop the execution, in order to avoid wasting computation power or memory resources.</p>
<p>When <code>observable.subscribe</code> is called, the Observer gets attached to the newly created Observable execution, but also this call returns an object, the <code>Subscription</code>:</p>
<p><!-- skip-example -->
</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var subscription = observable.subscribe(x => console.log(x));</code>
</code></pre>
<p>The Subscription represents the ongoing execution, and has a minimal API which allows you to cancel that execution. Read more about the <a href="./manual/./overview.html#subscription"><code>Subscription</code> type here</a>. With <code>subscription.unsubscribe()</code> you can cancel the ongoing execution:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable = Rx.Observable.from([10, 20, 30]);
var subscription = observable.subscribe(x => console.log(x));
// Later:
subscription.unsubscribe();</code>
</code></pre>
<p><span class="informal">When you subscribe, you get back a Subscription, which represents the ongoing execution. Just call <code>unsubscribe()</code> to cancel the execution.</span></p>
<p>Each Observable must define how to dispose resources of that execution when we create the Observable using <code>create()</code>. You can do that by returning a custom <code>unsubscribe</code> function from within <code>function subscribe()</code>.</p>
<p>For instance, this is how we clear an interval execution set with <code>setInterval</code>:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable = Rx.Observable.create(function subscribe(observer) {
// Keep track of the interval resource
var intervalID = setInterval(() => {
observer.next('hi');
}, 1000);
// Provide a way of canceling and disposing the interval resource
return function unsubscribe() {
clearInterval(intervalID);
};
});</code>
</code></pre>
<p>Just like <code>observable.subscribe</code> resembles <code>Observable.create(function subscribe() {...})</code>, the <code>unsubscribe</code> we return from <code>subscribe</code> is conceptually equal to <code>subscription.unsubscribe</code>. In fact, if we remove the ReactiveX types surrounding these concepts, we're left with rather straightforward JavaScript.</p>
<pre><code class="lang-js"><code class="source-code prettyprint">function subscribe(observer) {
var intervalID = setInterval(() => {
observer.next('hi');
}, 1000);
return function unsubscribe() {
clearInterval(intervalID);
};
}
var unsubscribe = subscribe({next: (x) => console.log(x)});
// Later:
unsubscribe(); // dispose the resources</code>
</code></pre>
<p>The reason why we use Rx types like Observable, Observer, and Subscription is to get safety (such as the Observable Contract) and composability with Operators.</p>
<h1 id="observer">Observer</h1>
<p><strong>What is an Observer?</strong> An Observer is a consumer of values delivered by an Observable. Observers are simply a set of callbacks, one for each type of notification delivered by the Observable: <code>next</code>, <code>error</code>, and <code>complete</code>. The following is an example of a typical Observer object:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observer = {
next: x => console.log('Observer got a next value: ' + x),
error: err => console.error('Observer got an error: ' + err),
complete: () => console.log('Observer got a complete notification'),
};</code>
</code></pre>
<p>To use the Observer, provide it to the <code>subscribe</code> of an Observable:</p>
<p><!-- skip-example -->
</p>
<pre><code class="lang-js"><code class="source-code prettyprint">observable.subscribe(observer);</code>
</code></pre>
<p><span class="informal">Observers are just objects with three callbacks, one for each type of notification that an Observable may deliver.</span></p>
<p>Observers in RxJS may also be <em>partial</em>. If you don't provide one of the callbacks, the execution of the Observable will still happen normally, except some types of notifications will be ignored, because they don't have a corresponding callback in the Observer.</p>
<p>The example below is an Observer without the <code>complete</code> callback:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observer = {
next: x => console.log('Observer got a next value: ' + x),
error: err => console.error('Observer got an error: ' + err),
};</code>
</code></pre>
<p>When subscribing to an Observable, you may also just provide the callbacks as arguments, without being attached to an Observer object, for instance like this:</p>
<p><!-- skip-example -->
</p>
<pre><code class="lang-js"><code class="source-code prettyprint">observable.subscribe(x => console.log('Observer got a next value: ' + x));</code>
</code></pre>
<p>Internally in <code>observable.subscribe</code>, it will create an Observer object using the first callback argument as the <code>next</code> handler. All three types of callbacks may be provided as arguments:</p>
<p><!-- skip-example -->
</p>
<pre><code class="lang-js"><code class="source-code prettyprint">observable.subscribe(
x => console.log('Observer got a next value: ' + x),
err => console.error('Observer got an error: ' + err),
() => console.log('Observer got a complete notification')
);</code>
</code></pre>
<h1 id="subscription">Subscription</h1>
<p><strong>What is a Subscription?</strong> A Subscription is an object that represents a disposable resource, usually the execution of an Observable. A Subscription has one important method, <code>unsubscribe</code>, that takes no argument and just disposes the resource held by the subscription. In previous versions of RxJS, Subscription was called "Disposable".</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable = Rx.Observable.interval(1000);
var subscription = observable.subscribe(x => console.log(x));
// Later:
// This cancels the ongoing Observable execution which
// was started by calling subscribe with an Observer.
subscription.unsubscribe();</code>
</code></pre>
<p><span class="informal">A Subscription essentially just has an <code>unsubscribe()</code> function to release resources or cancel Observable executions.</span></p>
<p>Subscriptions can also be put together, so that a call to an <code>unsubscribe()</code> of one Subscription may unsubscribe multiple Subscriptions. You can do this by "adding" one subscription into another:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var observable1 = Rx.Observable.interval(400);
var observable2 = Rx.Observable.interval(300);
var subscription = observable1.subscribe(x => console.log('first: ' + x));
var childSubscription = observable2.subscribe(x => console.log('second: ' + x));
subscription.add(childSubscription);
setTimeout(() => {
// Unsubscribes BOTH subscription and childSubscription
subscription.unsubscribe();
}, 1000);</code>
</code></pre>
<p>When executed, we see in the console:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">second: 0
first: 0
second: 1
first: 1
second: 2</code>
</code></pre>
<p>Subscriptions also have a <code>remove(otherSubscription)</code> method, in order to undo the addition of a child Subscription.</p>
<h1 id="subject">Subject</h1>
<p><strong>What is a Subject?</strong> An RxJS Subject is a special type of Observable that allows values to be multicasted to many Observers. While plain Observables are unicast (each subscribed Observer owns an independent execution of the Observable), Subjects are multicast.</p>
<p><span class="informal">A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.</span></p>
<p><strong>Every Subject is an Observable.</strong> Given a Subject, you can <code>subscribe</code> to it, providing an Observer, which will start receiving values normally. From the perspective of the Observer, it cannot tell whether the Observable execution is coming from a plain unicast Observable or a Subject.</p>
<p>Internally to the Subject, <code>subscribe</code> does not invoke a new execution that delivers values. It simply registers the given Observer in a list of Observers, similarly to how <code>addListener</code> usually works in other libraries and languages.</p>
<p><strong>Every Subject is an Observer.</strong> It is an object with the methods <code>next(v)</code>, <code>error(e)</code>, and <code>complete()</code>. To feed a new value to the Subject, just call <code>next(theValue)</code>, and it will be multicasted to the Observers registered to listen to the Subject.</p>
<p>In the example below, we have two Observers attached to a Subject, and we feed some values to the Subject:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var subject = new Rx.Subject();
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
subject.next(1);
subject.next(2);</code>
</code></pre>
<p>With the following output on the console:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">observerA: 1
observerB: 1
observerA: 2
observerB: 2</code>
</code></pre>
<p>Since a Subject is an Observer, this also means you may provide a Subject as the argument to the <code>subscribe</code> of any Observable, like the example below shows:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var subject = new Rx.Subject();
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
var observable = Rx.Observable.from([1, 2, 3]);
observable.subscribe(subject); // You can subscribe providing a Subject</code>
</code></pre>
<p>Which executes as:</p>
<pre><code class="lang-none"><code class="source-code prettyprint">observerA: 1
observerB: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3</code>
</code></pre>
<p>With the approach above, we essentially just converted a unicast Observable execution to multicast, through the Subject. This demonstrates how Subjects are the only way of making any Observable execution be shared to multiple Observers.</p>
<p>There are also a few specializations of the <code>Subject</code> type: <code>BehaviorSubject</code>, <code>ReplaySubject</code>, and <code>AsyncSubject</code>.</p>
<h2 id="multicasted-observables">Multicasted Observables</h2>
<p>A "multicasted Observable" passes notifications through a Subject which may have many subscribers, whereas a plain "unicast Observable" only sends notifications to a single Observer.</p>
<p><span class="informal">A multicasted Observable uses a Subject under the hood to make multiple Observers see the same Observable execution.</span></p>
<p>Under the hood, this is how the <code>multicast</code> operator works: Observers subscribe to an underlying Subject, and the Subject subscribes to the source Observable. The following example is similar to the previous example which used <code>observable.subscribe(subject)</code>:</p>
<pre><code class="lang-js"><code class="source-code prettyprint">var source = Rx.Observable.from([1, 2, 3]);
var subject = new Rx.Subject();
var multicasted = source.multicast(subject);
// These are, under the hood, `subject.subscribe({...})`:
multicasted.subscribe({
next: (v) => console.log('observerA: ' + v)
});
multicasted.subscribe({
next: (v) => console.log('observerB: ' + v)
});
// This is, under the hood, `source.subscribe(subject)`:
multicasted.connect();</code>
</code></pre>
<p><code>multicast</code> returns an Observable that looks like a normal Observable, but works like a Subject when it comes to subscribing. <code>multicast</code> returns a <code>ConnectableObservable</code>, which is simply an Observable with the <code>connect()</code> method.</p>
<p>The <code>connect()</code> method is important to determine exactly when the shared Observable execution will start. Because <code>connect()</code> does <code>source.subscribe(subject)</code> under the hood, <code>connect()</code> returns a Subscription, which you can unsubscribe from in order to cancel the shared Observable execution.</p>
<h3 id="reference-counting">Reference counting</h3>
<p>Calling <code>connect()</code> manually and handling the Subscription is often cumbersome. Usually, we want to <em>automatically</em> connect when the first Observer arrives, and automatically cancel the shared execution when the last Observer unsubscribes.</p>
<p>Consider the following example where subscriptions occur as outlined by this list:</p>
<ol>
<li>First Observer subscribes to the multicasted Obser