Gerard Sans | Axiom 🇬🇧 PRO
Founder of Axiom Masterclass, professional trainings // Forging skills for the new era of AI. GDE in AI, Cloud & Angular. Building London's tech & art nexus @nextai_london. Speaker | MC | Trainer.
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 2ajax, 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);
}));
});
});
By Gerard Sans | Axiom 🇬🇧
In this talk I will be covering High Order Observables and how to master them. These Observables emit other Observables and require specific operators. I will explain how RxJS Core developers deal with complex Observables orchestration and how you can use this knowledge to take your RxJS skills to new heights!
Founder of Axiom Masterclass, professional trainings // Forging skills for the new era of AI. GDE in AI, Cloud & Angular. Building London's tech & art nexus @nextai_london. Speaker | MC | Trainer.