Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / rxjs / src / internal / operators / single.ts
1 import { Observable } from '../Observable';
2 import { Operator } from '../Operator';
3 import { Subscriber } from '../Subscriber';
4 import { EmptyError } from '../util/EmptyError';
5
6 import { Observer, MonoTypeOperatorFunction, TeardownLogic } from '../types';
7
8 /**
9  * Returns an Observable that emits the single item emitted by the source Observable that matches a specified
10  * predicate, if that Observable emits one such item. If the source Observable emits more than one such item or no
11  * items, notify of an IllegalArgumentException or NoSuchElementException respectively. If the source Observable
12  * emits items but none match the specified predicate then `undefined` is emitted.
13  *
14  * <span class="informal">Like {@link first}, but emit with error notification if there is more than one value.</span>
15  * ![](single.png)
16  *
17  * ## Example
18  * emits 'error'
19  * ```ts
20  * import { range } from 'rxjs';
21  * import { single } from 'rxjs/operators';
22  *
23  * const numbers = range(1,5).pipe(single());
24  * numbers.subscribe(x => console.log('never get called'), e => console.log('error'));
25  * // result
26  * // 'error'
27  * ```
28  *
29  * emits 'undefined'
30  * ```ts
31  * import { range } from 'rxjs';
32  * import { single } from 'rxjs/operators';
33  *
34  * const numbers = range(1,5).pipe(single(x => x === 10));
35  * numbers.subscribe(x => console.log(x));
36  * // result
37  * // 'undefined'
38  * ```
39  *
40  * @see {@link first}
41  * @see {@link find}
42  * @see {@link findIndex}
43  * @see {@link elementAt}
44  *
45  * @throws {EmptyError} Delivers an EmptyError to the Observer's `error`
46  * callback if the Observable completes before any `next` notification was sent.
47  * @param {Function} predicate - A predicate function to evaluate items emitted by the source Observable.
48  * @return {Observable<T>} An Observable that emits the single item emitted by the source Observable that matches
49  * the predicate or `undefined` when no items match.
50  *
51  * @method single
52  * @owner Observable
53  */
54 export function single<T>(predicate?: (value: T, index: number, source: Observable<T>) => boolean): MonoTypeOperatorFunction<T> {
55   return (source: Observable<T>) => source.lift(new SingleOperator(predicate, source));
56 }
57
58 class SingleOperator<T> implements Operator<T, T> {
59   constructor(private predicate?: (value: T, index: number, source: Observable<T>) => boolean,
60               private source?: Observable<T>) {
61   }
62
63   call(subscriber: Subscriber<T>, source: any): TeardownLogic {
64     return source.subscribe(new SingleSubscriber(subscriber, this.predicate, this.source));
65   }
66 }
67
68 /**
69  * We need this JSDoc comment for affecting ESDoc.
70  * @ignore
71  * @extends {Ignored}
72  */
73 class SingleSubscriber<T> extends Subscriber<T> {
74   private seenValue: boolean = false;
75   private singleValue: T;
76   private index: number = 0;
77
78   constructor(destination: Observer<T>,
79               private predicate?: (value: T, index: number, source: Observable<T>) => boolean,
80               private source?: Observable<T>) {
81     super(destination);
82   }
83
84   private applySingleValue(value: T): void {
85     if (this.seenValue) {
86       this.destination.error('Sequence contains more than one element');
87     } else {
88       this.seenValue = true;
89       this.singleValue = value;
90     }
91   }
92
93   protected _next(value: T): void {
94     const index = this.index++;
95
96     if (this.predicate) {
97       this.tryNext(value, index);
98     } else {
99       this.applySingleValue(value);
100     }
101   }
102
103   private tryNext(value: T, index: number): void {
104     try {
105       if (this.predicate(value, index, this.source)) {
106         this.applySingleValue(value);
107       }
108     } catch (err) {
109       this.destination.error(err);
110     }
111   }
112
113   protected _complete(): void {
114     const destination = this.destination;
115
116     if (this.index > 0) {
117       destination.next(this.seenValue ? this.singleValue : undefined);
118       destination.complete();
119     } else {
120       destination.error(new EmptyError);
121     }
122   }
123 }