e855ff0a8a40336b0c83d98a32397dc42eb3593b
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / rxjs / src / internal / operators / throttle.ts
1 import { Operator } from '../Operator';
2 import { Observable } from '../Observable';
3 import { Subscriber } from '../Subscriber';
4 import { Subscription } from '../Subscription';
5
6 import { OuterSubscriber } from '../OuterSubscriber';
7 import { InnerSubscriber } from '../InnerSubscriber';
8 import { subscribeToResult } from '../util/subscribeToResult';
9
10 import { MonoTypeOperatorFunction, SubscribableOrPromise, TeardownLogic } from '../types';
11
12 export interface ThrottleConfig {
13   leading?: boolean;
14   trailing?: boolean;
15 }
16
17 export const defaultThrottleConfig: ThrottleConfig = {
18   leading: true,
19   trailing: false
20 };
21
22 /**
23  * Emits a value from the source Observable, then ignores subsequent source
24  * values for a duration determined by another Observable, then repeats this
25  * process.
26  *
27  * <span class="informal">It's like {@link throttleTime}, but the silencing
28  * duration is determined by a second Observable.</span>
29  *
30  * ![](throttle.png)
31  *
32  * `throttle` emits the source Observable values on the output Observable
33  * when its internal timer is disabled, and ignores source values when the timer
34  * is enabled. Initially, the timer is disabled. As soon as the first source
35  * value arrives, it is forwarded to the output Observable, and then the timer
36  * is enabled by calling the `durationSelector` function with the source value,
37  * which returns the "duration" Observable. When the duration Observable emits a
38  * value or completes, the timer is disabled, and this process repeats for the
39  * next source value.
40  *
41  * ## Example
42  * Emit clicks at a rate of at most one click per second
43  * ```ts
44  * import { fromEvent } from 'rxjs';
45  * import { throttle } from 'rxjs/operators';
46  *
47  * const clicks = fromEvent(document, 'click');
48  * const result = clicks.pipe(throttle(ev => interval(1000)));
49  * result.subscribe(x => console.log(x));
50  * ```
51  *
52  * @see {@link audit}
53  * @see {@link debounce}
54  * @see {@link delayWhen}
55  * @see {@link sample}
56  * @see {@link throttleTime}
57  *
58  * @param {function(value: T): SubscribableOrPromise} durationSelector A function
59  * that receives a value from the source Observable, for computing the silencing
60  * duration for each source value, returned as an Observable or a Promise.
61  * @param {Object} config a configuration object to define `leading` and `trailing` behavior. Defaults
62  * to `{ leading: true, trailing: false }`.
63  * @return {Observable<T>} An Observable that performs the throttle operation to
64  * limit the rate of emissions from the source.
65  * @method throttle
66  * @owner Observable
67  */
68 export function throttle<T>(durationSelector: (value: T) => SubscribableOrPromise<any>,
69                             config: ThrottleConfig = defaultThrottleConfig): MonoTypeOperatorFunction<T> {
70   return (source: Observable<T>) => source.lift(new ThrottleOperator(durationSelector, config.leading, config.trailing));
71 }
72
73 class ThrottleOperator<T> implements Operator<T, T> {
74   constructor(private durationSelector: (value: T) => SubscribableOrPromise<any>,
75               private leading: boolean,
76               private trailing: boolean) {
77   }
78
79   call(subscriber: Subscriber<T>, source: any): TeardownLogic {
80     return source.subscribe(
81       new ThrottleSubscriber(subscriber, this.durationSelector, this.leading, this.trailing)
82     );
83   }
84 }
85
86 /**
87  * We need this JSDoc comment for affecting ESDoc
88  * @ignore
89  * @extends {Ignored}
90  */
91 class ThrottleSubscriber<T, R> extends OuterSubscriber<T, R> {
92   private _throttled: Subscription;
93   private _sendValue: T;
94   private _hasValue = false;
95
96   constructor(protected destination: Subscriber<T>,
97               private durationSelector: (value: T) => SubscribableOrPromise<number>,
98               private _leading: boolean,
99               private _trailing: boolean) {
100     super(destination);
101   }
102
103   protected _next(value: T): void {
104     this._hasValue = true;
105     this._sendValue = value;
106
107     if (!this._throttled) {
108       if (this._leading) {
109         this.send();
110       } else {
111         this.throttle(value);
112       }
113     }
114   }
115
116   private send() {
117     const { _hasValue, _sendValue } = this;
118     if (_hasValue) {
119       this.destination.next(_sendValue);
120       this.throttle(_sendValue);
121     }
122     this._hasValue = false;
123     this._sendValue = null;
124   }
125
126   private throttle(value: T): void {
127     const duration = this.tryDurationSelector(value);
128     if (!!duration) {
129       this.add(this._throttled = subscribeToResult(this, duration));
130     }
131   }
132
133   private tryDurationSelector(value: T): SubscribableOrPromise<any> {
134     try {
135       return this.durationSelector(value);
136     } catch (err) {
137       this.destination.error(err);
138       return null;
139     }
140   }
141
142   private throttlingDone() {
143     const { _throttled, _trailing } = this;
144     if (_throttled) {
145       _throttled.unsubscribe();
146     }
147     this._throttled = null;
148
149     if (_trailing) {
150       this.send();
151     }
152   }
153
154   notifyNext(outerValue: T, innerValue: R,
155              outerIndex: number, innerIndex: number,
156              innerSub: InnerSubscriber<T, R>): void {
157     this.throttlingDone();
158   }
159
160   notifyComplete(): void {
161     this.throttlingDone();
162   }
163 }