Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 6dda55c

Browse files
Added section on operators
1 parent 0bd6813 commit 6dda55c

File tree

5 files changed

+173
-6
lines changed

5 files changed

+173
-6
lines changed

public/docs/_examples/rxjs/ts/app/hero-counter.component.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// #docplaster
22
// #docregion
3+
import 'rxjs/add/operator/takeUntil';
34
import { Component, OnInit, OnDestroy } from '@angular/core';
45
import { Subject } from 'rxjs/Subject';
56
import { Observable } from 'rxjs/Observable';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// #docplaster
2+
// #docregion
3+
// #docregion operator-import
4+
import 'rxjs/add/operator/do';
5+
import 'rxjs/add/operator/filter';
6+
// #docregion operator
7+
import { Component, OnInit } from '@angular/core';
8+
9+
import { HeroService } from './hero.service';
10+
import { Hero } from './hero';
11+
12+
@Component({
13+
template: `
14+
<h2>HEROES</h2>
15+
<ul class="items">
16+
<li *ngFor="let hero of heroes">
17+
<span class="badge">{{ hero.id }}</span> {{ hero.name }}
18+
</li>
19+
</ul>
20+
`
21+
})
22+
export class HeroListComponent implements OnInit {
23+
heroes: Hero[];
24+
25+
constructor(
26+
private service: HeroService
27+
) {}
28+
29+
ngOnInit() {
30+
this.service.getHeroes()
31+
.do(heroes => {
32+
console.log(heroes.length);
33+
})
34+
.filter(heroes => heroes.length > 2)
35+
.subscribe(heroes => this.heroes = heroes);
36+
}
37+
}
38+
// #enddocregion operator-import
39+
40+
// #docregion import-all
41+
import 'rxjs/Rx';
42+
// #enddocregion import-all
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// #docplaster
2+
// #docregion
3+
import { _do } from 'rxjs/operator/do';
4+
import { filter } from 'rxjs/operator/filter';
5+
import { Component, OnInit } from '@angular/core';
6+
7+
import { HeroService } from './hero.service';
8+
import { Hero } from './hero';
9+
10+
@Component({
11+
template: `
12+
<h2>HEROES</h2>
13+
<ul class="items">
14+
<li *ngFor="let hero of heroes">
15+
<span class="badge">{{ hero.id }}</span> {{ hero.name }}
16+
</li>
17+
</ul>
18+
`
19+
})
20+
export class HeroListComponent implements OnInit {
21+
heroes: Hero[];
22+
23+
constructor(
24+
private service: HeroService
25+
) {}
26+
27+
ngOnInit() {
28+
const heroes$ = this.service.getHeroes();
29+
const loggedHeroes$ = _do.call(heroes$, (heroes: Hero[]) => {
30+
console.log(heroes.length);
31+
});
32+
const filteredHeroes$ = filter.call(loggedHeroes$, (heroes: Hero[]) => heroes.length > 2);
33+
34+
filteredHeroes$.subscribe((heroes: Hero[]) => this.heroes = heroes);
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// #docplaster
2+
// #docregion
3+
// #docregion filter-import
4+
import 'rxjs/add/operator/filter';
5+
// #enddocregion filter-import
6+
// #docregion operator
7+
import { Component, OnInit } from '@angular/core';
8+
9+
import { HeroService } from './hero.service';
10+
import { Hero } from './hero';
11+
12+
@Component({
13+
template: `
14+
<h2>HEROES</h2>
15+
<ul class="items">
16+
<li *ngFor="let hero of heroes">
17+
<span class="badge">{{ hero.id }}</span> {{ hero.name }}
18+
</li>
19+
</ul>
20+
`
21+
})
22+
export class HeroListComponent implements OnInit {
23+
heroes: Hero[];
24+
25+
constructor(
26+
private service: HeroService
27+
) {}
28+
29+
ngOnInit() {
30+
this.service.getHeroes()
31+
.filter(heroes => heroes.length > 2)
32+
.subscribe(heroes => this.heroes = heroes);
33+
}
34+
}
35+
// #enddocregion

public/docs/ts/latest/guide/rxjs.jade

+59-6
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@ block includes
1616
## Table of Contents
1717
* [The Observable](#definition "")
1818
* [Observables and Promises](#observables-vs-promises "")
19-
* [Framework APIs](#apis "")
19+
* [Using Operators](#operators "")
20+
* [Managing Subscriptions](#managing-subscriptions "")
21+
* [Sharing Data](#sharing-data "")
2022
* [Error Handling](#error-handling "")
21-
* [Further Reading](#reading "")
23+
* [Framework APIs](#framework-apis "")
24+
* [Stream Integration](#integration "")
25+
* [Further Reading](#further-reading "")
2226

2327
h3#definition The Observable: a function at its core
2428

@@ -61,10 +65,59 @@ h3#observables-vs-promises Observables and Promises: More different than alike
6165
tool to handle the various streams of events in an application. So does this mean Promises are no longer needed? Absolutely not. Promises will continue to serve a purpose as
6266
the right tool for the job in some situations.
6367

68+
h3#operators Operators: Import them and use them
69+
70+
:marked
71+
Operators are pure functions that extend the Observable interface, allow you to perform an action against the Observable
72+
and return a new Observable. An Observable comes with very few built-in operators and the rest of the operators are
73+
added to the Observable on demand. There are multiple approaches to make these operators available for use.
74+
One approach is to import the entire RxJS library.
75+
76+
+makeExcerpt('app/heroes-filtered.component.1.ts', 'import-all')
77+
78+
:marked
79+
This is the **least recommended** method, as it brings in **all** the Observables operators,
80+
even ones you never use. While convenient, this method is inefficient and can greatly impact the size of your application,
81+
which is always a concern. This method is mainly reserved for prototyping and testing, where such concerns are less important.
82+
83+
The second method is to import operators selectively by patching the Observable prototype. This allows you to chain
84+
operators together, as each operator returns a new Observable. Below is an example of importing the `filter` and `do` operators.
85+
The `filter` operator filters elements produced by an Observable based on a predicate function that returns a boolean. The `do` operator
86+
provides the Observable value to perform an arbitrary action, such as console logging.
87+
88+
+makeExcerpt('app/heroes-filtered.component.1.ts', 'operator-import')
89+
90+
:marked
91+
Had you not imported these common operators before using them with the Observable returned by `getHeroes`,
92+
the Observable would fail to perform these actions as it these functions don't exist on the Observable yet.
93+
94+
Another common example is two components with incomplete operator imports. Both files have components that use Observable operators
95+
but only one file imports the operators it needs. Interestingly enough if you load the component with the imported operators first and then
96+
load the second component, everything works fine. Conversely, loading the component without the imported operators first blows up because the
97+
operators aren't available on the Observable.
98+
99+
Another approach is to import the Observable operators directly and call them individually on the Observable. Let's
100+
update your filtered heroes component to use direct imports.
101+
102+
+makeExcerpt('app/heroes-filtered.component.2.ts (direct operator imports)', '')
103+
104+
:marked
105+
This approach has no side-effects as you're not patching the Observable prototype. It also is
106+
more conducive to tree shaking versus patching the Observable prototype, which can't be tree-shaken. You're also only importing what you need where you need it,
107+
but this approach doesn't give you the option to chain operators together. If you were building a third-party
108+
library, this would be the recommended approach as you don't want your library to produce any side-effects
109+
to the Observable for consumers of your library but for an application, its less desirable.
110+
111+
The recommended approach is to import the operators in the file where you use them. Yes, this may lead to
112+
duplicate imports of operators in multiple files, but more importantly this ensures that the operators
113+
that are needed are provided by that file. This becomes especially important with lazy loading, where
114+
certain feature areas may only make use of certain operators. Importing the operators this way ensures
115+
the operators are available regardless of where and when you use them.
116+
64117
h3#managing-subscriptions Managing Subscriptions
65118

66119
:marked
67-
Observables like any other instance use resources and those resources add to the overall resources used in your application. Observables
120+
Observables like any other instance use resources and those resources add to the overall weight of your application over time. Observables
68121
provide a `Subscription` for each `Subscriber` of the Observable that comes with a way to _unsubscribe_ or clean up any resources used
69122
while listening for values produced by the Observable. We'll look at a simple example of how to unsubscribe from and Observable once
70123
its no longer needed.
@@ -249,9 +302,9 @@ h3#framework-apis Framework APIs: Angular-provided streams
249302

250303
h3#integration Stream Integration
251304
:marked
252-
The Observables provided by these area can be used together. The same set of functionality and extensibility can be combined together in a very powerful and
253-
practical way. In order to demonstrate how these work together, you’re going to build a hero search component. Let’s start by gathering some requirements about
254-
what your typeahead will need.
305+
The Observables provided by these areas can be used together. The same set of functionality and extensibility can be combined together
306+
in a very powerful and practical way. A prime example is a hero search component that implements a typeahead search feature.
307+
Let’s start by gathering some requirements about what your typeahead will need.
255308

256309
* Take input from the user
257310
* Make a search based on that input

0 commit comments

Comments
 (0)