source: trip-planner-front/node_modules/rxjs/src/internal/operators/switchMap.ts@ 8d391a1

Last change on this file since 8d391a1 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.0 KB
Line 
1import { Operator } from '../Operator';
2import { Observable } from '../Observable';
3import { Subscriber } from '../Subscriber';
4import { Subscription } from '../Subscription';
5import { ObservableInput, OperatorFunction, ObservedValueOf } from '../types';
6import { map } from './map';
7import { from } from '../observable/from';
8import { SimpleOuterSubscriber, SimpleInnerSubscriber, innerSubscribe } from '../innerSubscribe';
9
10/* tslint:disable:max-line-length */
11export function switchMap<T, O extends ObservableInput<any>>(project: (value: T, index: number) => O): OperatorFunction<T, ObservedValueOf<O>>;
12/** @deprecated resultSelector is no longer supported, use inner map instead */
13export function switchMap<T, O extends ObservableInput<any>>(project: (value: T, index: number) => O, resultSelector: undefined): OperatorFunction<T, ObservedValueOf<O>>;
14/** @deprecated resultSelector is no longer supported, use inner map instead */
15export function switchMap<T, R, O extends ObservableInput<any>>(project: (value: T, index: number) => O, resultSelector: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R): OperatorFunction<T, R>;
16/* tslint:enable:max-line-length */
17
18/**
19 * Projects each source value to an Observable which is merged in the output
20 * Observable, emitting values only from the most recently projected Observable.
21 *
22 * <span class="informal">Maps each value to an Observable, then flattens all of
23 * these inner Observables.</span>
24 *
25 * ![](switchMap.png)
26 *
27 * Returns an Observable that emits items based on applying a function that you
28 * supply to each item emitted by the source Observable, where that function
29 * returns an (so-called "inner") Observable. Each time it observes one of these
30 * inner Observables, the output Observable begins emitting the items emitted by
31 * that inner Observable. When a new inner Observable is emitted, `switchMap`
32 * stops emitting items from the earlier-emitted inner Observable and begins
33 * emitting items from the new one. It continues to behave like this for
34 * subsequent inner Observables.
35 *
36 * ## Example
37 * Generate new Observable according to source Observable values
38 * ```typescript
39 * import { of } from 'rxjs';
40 * import { switchMap } from 'rxjs/operators';
41 *
42 * const switched = of(1, 2, 3).pipe(switchMap((x: number) => of(x, x ** 2, x ** 3)));
43 * switched.subscribe(x => console.log(x));
44 * // outputs
45 * // 1
46 * // 1
47 * // 1
48 * // 2
49 * // 4
50 * // 8
51 * // ... and so on
52 * ```
53 *
54 * Rerun an interval Observable on every click event
55 * ```ts
56 * import { fromEvent, interval } from 'rxjs';
57 * import { switchMap } from 'rxjs/operators';
58 *
59 * const clicks = fromEvent(document, 'click');
60 * const result = clicks.pipe(switchMap((ev) => interval(1000)));
61 * result.subscribe(x => console.log(x));
62 * ```
63 *
64 * @see {@link concatMap}
65 * @see {@link exhaustMap}
66 * @see {@link mergeMap}
67 * @see {@link switchAll}
68 * @see {@link switchMapTo}
69 *
70 * @param {function(value: T, ?index: number): ObservableInput} project A function
71 * that, when applied to an item emitted by the source Observable, returns an
72 * Observable.
73 * @return {Observable} An Observable that emits the result of applying the
74 * projection function (and the optional deprecated `resultSelector`) to each item
75 * emitted by the source Observable and taking only the values from the most recently
76 * projected inner Observable.
77 * @method switchMap
78 * @owner Observable
79 */
80export function switchMap<T, R, O extends ObservableInput<any>>(
81 project: (value: T, index: number) => O,
82 resultSelector?: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R,
83): OperatorFunction<T, ObservedValueOf<O>|R> {
84 if (typeof resultSelector === 'function') {
85 return (source: Observable<T>) => source.pipe(
86 switchMap((a, i) => from(project(a, i)).pipe(
87 map((b, ii) => resultSelector(a, b, i, ii))
88 ))
89 );
90 }
91 return (source: Observable<T>) => source.lift(new SwitchMapOperator(project));
92}
93
94class SwitchMapOperator<T, R> implements Operator<T, R> {
95 constructor(private project: (value: T, index: number) => ObservableInput<R>) {
96 }
97
98 call(subscriber: Subscriber<R>, source: any): any {
99 return source.subscribe(new SwitchMapSubscriber(subscriber, this.project));
100 }
101}
102
103/**
104 * We need this JSDoc comment for affecting ESDoc.
105 * @ignore
106 * @extends {Ignored}
107 */
108class SwitchMapSubscriber<T, R> extends SimpleOuterSubscriber<T, R> {
109 private index = 0;
110 private innerSubscription?: Subscription;
111
112 constructor(destination: Subscriber<R>,
113 private project: (value: T, index: number) => ObservableInput<R>) {
114 super(destination);
115 }
116
117 protected _next(value: T) {
118 let result: ObservableInput<R>;
119 const index = this.index++;
120 try {
121 result = this.project(value, index);
122 } catch (error) {
123 this.destination.error!(error);
124 return;
125 }
126 this._innerSub(result);
127 }
128
129 private _innerSub(result: ObservableInput<R>) {
130 const innerSubscription = this.innerSubscription;
131 if (innerSubscription) {
132 innerSubscription.unsubscribe();
133 }
134 const innerSubscriber = new SimpleInnerSubscriber(this);
135 const destination = this.destination as Subscription;
136 destination.add(innerSubscriber);
137 this.innerSubscription = innerSubscribe(result, innerSubscriber);
138 // The returned subscription will usually be the subscriber that was
139 // passed. However, interop subscribers will be wrapped and for
140 // unsubscriptions to chain correctly, the wrapper needs to be added, too.
141 if (this.innerSubscription !== innerSubscriber) {
142 destination.add(this.innerSubscription);
143 }
144 }
145
146 protected _complete(): void {
147 const {innerSubscription} = this;
148 if (!innerSubscription || innerSubscription.closed) {
149 super._complete();
150 }
151 this.unsubscribe();
152 }
153
154 protected _unsubscribe() {
155 this.innerSubscription = undefined;
156 }
157
158 notifyComplete(): void {
159 this.innerSubscription = undefined;
160 if (this.isStopped) {
161 super._complete();
162 }
163 }
164
165 notifyNext(innerValue: R): void {
166 this.destination.next!(innerValue);
167 }
168}
Note: See TracBrowser for help on using the repository browser.