Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / rxjs / src / internal / operators / switchMap.ts
1 import { Operator } from '../Operator';
2 import { Observable } from '../Observable';
3 import { Subscriber } from '../Subscriber';
4 import { Subscription } from '../Subscription';
5 import { ObservableInput, OperatorFunction, ObservedValueOf } from '../types';
6 import { map } from './map';
7 import { from } from '../observable/from';
8 import { SimpleOuterSubscriber, SimpleInnerSubscriber, innerSubscribe } from '../innerSubscribe';
9
10 /* tslint:disable:max-line-length */
11 export 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 */
13 export 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 */
15 export 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  */
80 export 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
94 class 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  */
108 class 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 }