by Gerard Sans (@gerardsans)
Spoken at 59 events in 19 countries
900
1.2K
Angular In Flip Flops
Angular Academy
Observable
Timeline
Emitted values
complete
next
next
next
Observable
Timeline
next
next
error
// --1--1--1|
let a$ = Rx.Observable.create(observer => {
observer.next(1);
observer.next(1);
observer.next(1);
observer.complete();
});
let subscription = a$.subscribe({
next: v => l(v),
complete: () => l('|')
});
subscription.unsubscribe();
// --1--1--#
let a$ = Rx.Observable.create(observer => {
try {
observer.next(1);
observer.next(1);
throw('Ups!');
observer.complete();
}
catch(e) {
observer.error(e);
}
});
let subscription = a$.subscribe({
next: v => l(v),
complete: () => l('|'),
error: (e) => l('#')
});
interval(1000).pipe(
take(3),
filter(v=>v%2==0)
);
// a) --0--1--2|
// b) --0-----2|
// c) --------2|
of(1).subscribe({
next: x => log(x),
complete: () => log('3')
});
log('2');
// a) 1 2 3
// b) 2 1 3
// c) 1 3 2
ajax, audit, auditTime, bindCallback, bindNodeCallback, buffer, bufferCount, bufferTime, bufferToggle, bufferWhen, cache, catch, combineAll, combineLatest, concat, concatAll, concatMap, concatMapTo, count, create, debounce, debounceTime, defaultIfEmpty, defer, delay, delayWhen, dematerialize, distinct, distinctKey, distinctUntilChanged, distinctUntilKeyChanged, do, elementAt, empty, every, exhaust, exhaustMap, expand, filter, finally, find, findIndex, first, forkJoin, from, fromEvent, fromEventPattern, fromPromise, generate, groupBy, ignoreElements, interval, isEmpty, last, let, map, mapTo, materialize, max, merge, mergeAll, mergeMap, mergeMapTo, mergeScan, min, multicast, never, observeOn, of, pairwise, partition, pluck, publish, publishBehavior, publishLast, publishReplay, race, range, reduce, repeat, repeatWhen, retry, retryWhen, sample, sampleTime, scan, share, single, skip, skipLast, skipUntil, skipWhile, startWith, subscribeOn, switch, switchMap, switchMapTo, take, takeLast, takeUntil, takeWhile, throttle, throttleTime, throw, timeInterval, timeout, timeoutWith, timer, timestamp, toArray, toPromise, Utility Operators, window, windowCount, windowTime, windowToggle, windowWhen, withLatestFrom, zip, zipAll
1
Cold
subscriber1
1
1
subscriber2
Timeline
subscribe
subscribe
import {marbles} from "rxjs-marbles";
describe("Cold Observables", () => {
describe("basic marbles", () => {
it("should support simple values as strings", marbles(m => {
const input = m.cold("--1--1|");
const expected = m.cold("--1--2|");
const output = input.map(x => x);
m.expect(output).toBeObservable(expected);
}));
});
});
const input = m.cold("--1--1|");
const expected = m.cold("--1--2|");
...
Cold Observables basic marbles should support simple values as strings
Error:
Expected
{"frame":20,"notification":{"kind":"N","value":"1","hasValue":true}}
{"frame":50,"notification":{"kind":"N","value":"1","hasValue":true}}
{"frame":60,"notification":{"kind":"C","hasValue":false}}
to deep equal
{"frame":20,"notification":{"kind":"N","value":"1","hasValue":true}}
{"frame":50,"notification":{"kind":"N","value":"2","hasValue":true}}
{"frame":60,"notification":{"kind":"C","hasValue":false}}
import {marbles} from "rxjs-marbles";
describe("Cold Observables", () => {
describe("basic marbles", () => {
it("should support simple values as strings", marbles(m => {
const values = { a: 1, b: 2 };
const input = m.cold("--a--a|", values);
const expected = m.cold("--b--b|", values);
const output = input.map(x => x+1);
m.expect(output).toBeObservable(expected);
}));
});
});
import {marbles} from "rxjs-marbles";
describe("Cold Observables", () => {
describe("basic marbles", () => {
it("should support custom Observables", marbles(m => {
const input = Observable.throw(new Error('Ups')));
const expected = m.cold("#", undefined, new Error('Ups'));
const output = input.map(x => x);
m.expect(output).toBeObservable(expected);
}));
});
});
1
Hot
subscriber1
1
1
subscriber2
Timeline
subscribe
subscribe
import {marbles} from "rxjs-marbles";
describe("Hot Observables", () => {
describe("Subscriptions", () => {
it("should support basic subscriptions", marbles(m => {
const values = { a: 1, b: 2 };
const input = m.hot( "--a^-a|", values);
const expected = m.cold( "--b|", values);
const output = input.map(x => x+1);
m.expect(output).toBeObservable(expected);
}));
});
});
import {marbles} from "rxjs-marbles";
describe("Hot Observables", () => {
describe("Subscriptions", () => {
it("should support testing subscriptions", marbles(m => {
const values = { a: 1, b: 2 };
const input = m.hot( "--a^-a|", values);
const subs = "^-!";
const expected = m.cold( "--b|", values);
const output = input.map(x => x+1);
m.expect(output).toBeObservable(expected);
m.expect(input).toHaveSubscriptions(subs);
}));
});
});
const values = { a: 1, b: 2 };
const input = m.hot( "--a^-a|", values);
const subs = "^-!";
const expected = m.cold( "--b|", values);
...
Hot Observables Subscriptions should support complex subscriptions
Error:
Expected
{"subscribedFrame":0,"unsubscribedFrame":30}
to deep equal
{"subscribedFrame":0,"unsubscribedFrame":20}
subscribe to all inner observables
a
output
projected1
projected2
a.mergeMap(v => b.map(x => v*x))
b
v
x
x
x
v
x
x
x
x
x
x
import {marbles} from "rxjs-marbles";
describe("High Order Observables", () => {
describe("mergeMap", () => {
it("should subscribe to all inner observables", marbles(m => {
const values = { a: 1, b: 3, x: 10, i: 10, j: 30 };
const a = m.cold("--a--b--|", values);
const b = m.cold("x----x----x|", values);
const expected = m.cold("--i--j-i--j-i--j|", values);
const subs = "^---------------!";
const output = a.mergeMap(v => b.map(x => v*x));
m.expect(output).toBeObservable(expected);
m.expect(a).toHaveSubscriptions(subs);
}));
});
});
unsubscribe from latest inner observable subscribe to new
a.switchMap(v => b.map(x => v*x))
a
projected1
projected2
b
output
v
x
x
x
v
x
x
x
x
x
x
import {marbles} from "rxjs-marbles";
describe("High Order Observables", () => {
describe("switchMap", () => {
it("should unsubscribe from last inner observable", marbles(m => {
const values = { a: 1, b: 3, x: 10, i: 10, j: 30 };
const a = m.cold("--a--b--|", values);
const b = m.cold("x--x--x|", values);
const expected = m.cold("--i--j--j--j|", values);
const subs = "^-----------!";
const output = a.switchMap(v => b.map(x => v*x));
m.expect(output).toBeObservable(expected);
m.expect(a).toHaveSubscriptions(subs);
}));
});
});