source: trip-planner-front/node_modules/rxjs/src/internal/operators/bufferToggle.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: 5.6 KB
Line 
1import { Operator } from '../Operator';
2import { Subscriber } from '../Subscriber';
3import { Observable } from '../Observable';
4import { Subscription } from '../Subscription';
5import { subscribeToResult } from '../util/subscribeToResult';
6import { OuterSubscriber } from '../OuterSubscriber';
7import { InnerSubscriber } from '../InnerSubscriber';
8import { OperatorFunction, SubscribableOrPromise } from '../types';
9
10/**
11 * Buffers the source Observable values starting from an emission from
12 * `openings` and ending when the output of `closingSelector` emits.
13 *
14 * <span class="informal">Collects values from the past as an array. Starts
15 * collecting only when `opening` emits, and calls the `closingSelector`
16 * function to get an Observable that tells when to close the buffer.</span>
17 *
18 * ![](bufferToggle.png)
19 *
20 * Buffers values from the source by opening the buffer via signals from an
21 * Observable provided to `openings`, and closing and sending the buffers when
22 * a Subscribable or Promise returned by the `closingSelector` function emits.
23 *
24 * ## Example
25 *
26 * Every other second, emit the click events from the next 500ms
27 *
28 * ```ts
29 * import { fromEvent, interval, EMPTY } from 'rxjs';
30 * import { bufferToggle } from 'rxjs/operators';
31 *
32 * const clicks = fromEvent(document, 'click');
33 * const openings = interval(1000);
34 * const buffered = clicks.pipe(bufferToggle(openings, i =>
35 * i % 2 ? interval(500) : EMPTY
36 * ));
37 * buffered.subscribe(x => console.log(x));
38 * ```
39 *
40 * @see {@link buffer}
41 * @see {@link bufferCount}
42 * @see {@link bufferTime}
43 * @see {@link bufferWhen}
44 * @see {@link windowToggle}
45 *
46 * @param {SubscribableOrPromise<O>} openings A Subscribable or Promise of notifications to start new
47 * buffers.
48 * @param {function(value: O): SubscribableOrPromise} closingSelector A function that takes
49 * the value emitted by the `openings` observable and returns a Subscribable or Promise,
50 * which, when it emits, signals that the associated buffer should be emitted
51 * and cleared.
52 * @return {Observable<T[]>} An observable of arrays of buffered values.
53 * @method bufferToggle
54 * @owner Observable
55 */
56export function bufferToggle<T, O>(
57 openings: SubscribableOrPromise<O>,
58 closingSelector: (value: O) => SubscribableOrPromise<any>
59): OperatorFunction<T, T[]> {
60 return function bufferToggleOperatorFunction(source: Observable<T>) {
61 return source.lift(new BufferToggleOperator<T, O>(openings, closingSelector));
62 };
63}
64
65class BufferToggleOperator<T, O> implements Operator<T, T[]> {
66
67 constructor(private openings: SubscribableOrPromise<O>,
68 private closingSelector: (value: O) => SubscribableOrPromise<any>) {
69 }
70
71 call(subscriber: Subscriber<T[]>, source: any): any {
72 return source.subscribe(new BufferToggleSubscriber(subscriber, this.openings, this.closingSelector));
73 }
74}
75
76interface BufferContext<T> {
77 buffer: T[];
78 subscription: Subscription;
79}
80
81/**
82 * We need this JSDoc comment for affecting ESDoc.
83 * @ignore
84 * @extends {Ignored}
85 */
86class BufferToggleSubscriber<T, O> extends OuterSubscriber<T, O> {
87 private contexts: Array<BufferContext<T>> = [];
88
89 constructor(destination: Subscriber<T[]>,
90 openings: SubscribableOrPromise<O>,
91 private closingSelector: (value: O) => SubscribableOrPromise<any> | void) {
92 super(destination);
93 this.add(subscribeToResult(this, openings));
94 }
95
96 protected _next(value: T): void {
97 const contexts = this.contexts;
98 const len = contexts.length;
99 for (let i = 0; i < len; i++) {
100 contexts[i].buffer.push(value);
101 }
102 }
103
104 protected _error(err: any): void {
105 const contexts = this.contexts;
106 while (contexts.length > 0) {
107 const context = contexts.shift()!;
108 context.subscription.unsubscribe();
109 context.buffer = null!;
110 context.subscription = null!;
111 }
112 this.contexts = null!;
113 super._error(err);
114 }
115
116 protected _complete(): void {
117 const contexts = this.contexts;
118 while (contexts.length > 0) {
119 const context = contexts.shift()!;
120 this.destination.next!(context.buffer);
121 context.subscription.unsubscribe();
122 context.buffer = null!;
123 context.subscription = null!;
124 }
125 this.contexts = null!;
126 super._complete();
127 }
128
129 notifyNext(outerValue: any, innerValue: O): void {
130 outerValue ? this.closeBuffer(outerValue) : this.openBuffer(innerValue);
131 }
132
133 notifyComplete(innerSub: InnerSubscriber<T, O>): void {
134 this.closeBuffer((<any> innerSub).context);
135 }
136
137 private openBuffer(value: O): void {
138 try {
139 const closingSelector = this.closingSelector;
140 const closingNotifier = closingSelector.call(this, value);
141 if (closingNotifier) {
142 this.trySubscribe(closingNotifier);
143 }
144 } catch (err) {
145 this._error(err);
146 }
147 }
148
149 private closeBuffer(context: BufferContext<T>): void {
150 const contexts = this.contexts;
151
152 if (contexts && context) {
153 const { buffer, subscription } = context;
154 this.destination.next!(buffer);
155 contexts.splice(contexts.indexOf(context), 1);
156 this.remove(subscription);
157 subscription.unsubscribe();
158 }
159 }
160
161 private trySubscribe(closingNotifier: any): void {
162 const contexts = this.contexts;
163
164 const buffer: Array<T> = [];
165 const subscription = new Subscription();
166 const context = { buffer, subscription };
167 contexts.push(context);
168
169 const innerSubscription = subscribeToResult(this, closingNotifier, context as any);
170
171 if (!innerSubscription || innerSubscription.closed) {
172 this.closeBuffer(context);
173 } else {
174 (innerSubscription as any).context = context;
175
176 this.add(innerSubscription);
177 subscription.add(innerSubscription);
178 }
179 }
180}
Note: See TracBrowser for help on using the repository browser.