Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / rxjs / src / internal / operators / throttleTime.ts
1 import { Operator } from '../Operator';
2 import { Subscriber } from '../Subscriber';
3 import { Subscription } from '../Subscription';
4 import { async } from '../scheduler/async';
5 import { Observable } from '../Observable';
6 import { ThrottleConfig, defaultThrottleConfig } from './throttle';
7 import { MonoTypeOperatorFunction, SchedulerLike, TeardownLogic } from '../types';
8
9 /**
10  * Emits a value from the source Observable, then ignores subsequent source
11  * values for `duration` milliseconds, then repeats this process.
12  *
13  * <span class="informal">Lets a value pass, then ignores source values for the
14  * next `duration` milliseconds.</span>
15  *
16  * ![](throttleTime.png)
17  *
18  * `throttleTime` emits the source Observable values on the output Observable
19  * when its internal timer is disabled, and ignores source values when the timer
20  * is enabled. Initially, the timer is disabled. As soon as the first source
21  * value arrives, it is forwarded to the output Observable, and then the timer
22  * is enabled. After `duration` milliseconds (or the time unit determined
23  * internally by the optional `scheduler`) has passed, the timer is disabled,
24  * and this process repeats for the next source value. Optionally takes a
25  * {@link SchedulerLike} for managing timers.
26  *
27  * ## Examples
28  *
29  * #### Limit click rate
30  *
31  * Emit clicks at a rate of at most one click per second
32  * ```ts
33  * import { fromEvent } from 'rxjs';
34  * import { throttleTime } from 'rxjs/operators';
35  *
36  * const clicks = fromEvent(document, 'click');
37  * const result = clicks.pipe(throttleTime(1000));
38  * result.subscribe(x => console.log(x));
39  * ```
40  *
41  * #### Double Click
42  *
43  * The following example only emits clicks which happen within a subsequent
44  * delay of 400ms of the previous click. This for example can emulate a double
45  * click. It makes use of the `trailing` parameter of the throttle configuration.
46  *
47  * ```ts
48  * import { fromEvent, asyncScheduler } from 'rxjs';
49  * import { throttleTime, withLatestFrom } from 'rxjs/operators';
50  *
51  * // defaultThottleConfig = { leading: true, trailing: false }
52  * const throttleConfig = {
53  *   leading: false,
54  *   trailing: true
55  * }
56  *
57  * const click = fromEvent(document, 'click');
58  * const doubleClick = click.pipe(
59  *   throttleTime(400, asyncScheduler, throttleConfig)
60  * );
61  *
62  * doubleClick.subscribe((throttleValue: Event) => {
63  *   console.log(`Double-clicked! Timestamp: ${throttleValue.timeStamp}`);
64  * });
65  * ```
66  *
67  * If you enable the `leading` parameter in this example, the output would be the primary click and
68  * the double click, but restricts additional clicks within 400ms.
69  *
70  * @see {@link auditTime}
71  * @see {@link debounceTime}
72  * @see {@link delay}
73  * @see {@link sampleTime}
74  * @see {@link throttle}
75  *
76  * @param {number} duration Time to wait before emitting another value after
77  * emitting the last value, measured in milliseconds or the time unit determined
78  * internally by the optional `scheduler`.
79  * @param {SchedulerLike} [scheduler=async] The {@link SchedulerLike} to use for
80  * managing the timers that handle the throttling.
81  * @param {Object} config a configuration object to define `leading` and
82  * `trailing` behavior. Defaults to `{ leading: true, trailing: false }`.
83  * @return {Observable<T>} An Observable that performs the throttle operation to
84  * limit the rate of emissions from the source.
85  * @method throttleTime
86  * @owner Observable
87  */
88 export function throttleTime<T>(duration: number,
89                                 scheduler: SchedulerLike = async,
90                                 config: ThrottleConfig = defaultThrottleConfig): MonoTypeOperatorFunction<T> {
91   return (source: Observable<T>) => source.lift(new ThrottleTimeOperator(duration, scheduler, config.leading, config.trailing));
92 }
93
94 class ThrottleTimeOperator<T> implements Operator<T, T> {
95   constructor(private duration: number,
96               private scheduler: SchedulerLike,
97               private leading: boolean,
98               private trailing: boolean) {
99   }
100
101   call(subscriber: Subscriber<T>, source: any): TeardownLogic {
102     return source.subscribe(
103       new ThrottleTimeSubscriber(subscriber, this.duration, this.scheduler, this.leading, this.trailing)
104     );
105   }
106 }
107
108 /**
109  * We need this JSDoc comment for affecting ESDoc.
110  * @ignore
111  * @extends {Ignored}
112  */
113 class ThrottleTimeSubscriber<T> extends Subscriber<T> {
114   private throttled: Subscription;
115   private _hasTrailingValue: boolean = false;
116   private _trailingValue: T = null;
117
118   constructor(destination: Subscriber<T>,
119               private duration: number,
120               private scheduler: SchedulerLike,
121               private leading: boolean,
122               private trailing: boolean) {
123     super(destination);
124   }
125
126   protected _next(value: T) {
127     if (this.throttled) {
128       if (this.trailing) {
129         this._trailingValue = value;
130         this._hasTrailingValue = true;
131       }
132     } else {
133       this.add(this.throttled = this.scheduler.schedule<DispatchArg<T>>(dispatchNext, this.duration, { subscriber: this }));
134       if (this.leading) {
135         this.destination.next(value);
136       } else if (this.trailing) {
137         this._trailingValue = value;
138         this._hasTrailingValue = true;
139       }
140     }
141   }
142
143   protected _complete() {
144     if (this._hasTrailingValue) {
145       this.destination.next(this._trailingValue);
146       this.destination.complete();
147     } else {
148       this.destination.complete();
149     }
150   }
151
152   clearThrottle() {
153     const throttled = this.throttled;
154     if (throttled) {
155       if (this.trailing && this._hasTrailingValue) {
156         this.destination.next(this._trailingValue);
157         this._trailingValue = null;
158         this._hasTrailingValue = false;
159       }
160       throttled.unsubscribe();
161       this.remove(throttled);
162       this.throttled = null;
163     }
164   }
165 }
166
167 interface DispatchArg<T> {
168   subscriber: ThrottleTimeSubscriber<T>;
169 }
170
171 function dispatchNext<T>(arg: DispatchArg<T>) {
172   const { subscriber } = arg;
173   subscriber.clearThrottle();
174 }