1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 1 1 1 12 12 12 1 12 12 12 1 12 1 1 12 1 12 12 12 12 12 12 6 6 6 6 6 6 1 61 61 61 75 1 4 4 1 5 5 5 5 1 12 1 40 40 40 1 26 26 26 1 1 10 10 10 10 10 10 10 1 18 18 18 18 18 18 1 16 | import {Operator} from '../Operator'; import {Subscriber} from '../Subscriber'; import {Observable} from '../Observable'; import {Scheduler} from '../Scheduler'; import {Action} from '../scheduler/Action'; import {asap} from '../scheduler/asap'; /** * Buffers values from the source for a specific time period. Optionally allows * new buffers to be set up at an interval. * * <img src="./img/bufferTime.png" width="100%"> * * @param {number} bufferTimeSpan the amount of time to fill each buffer for * before emitting them and clearing them. * @param {number} [bufferCreationInterval] the interval at which to start new * buffers. * @param {Scheduler} [scheduler] (optional, defaults to `asap` scheduler) The * scheduler on which to schedule the intervals that determine buffer * boundaries. * @returns {Observable<T[]>} an observable of arrays of buffered values. */ export function bufferTime<T>(bufferTimeSpan: number, IbufferCreationInterval: number = null, Ischeduler: Scheduler = asap): Observable<T[]> { return this.lift(new BufferTimeOperator(bufferTimeSpan, bufferCreationInterval, scheduler)); } class BufferTimeOperator<T> implements Operator<T, T[]> { constructor(private bufferTimeSpan: number, private bufferCreationInterval: number, private scheduler: Scheduler) { } call(subscriber: Subscriber<T[]>): Subscriber<T> { return new BufferTimeSubscriber( subscriber, this.bufferTimeSpan, this.bufferCreationInterval, this.scheduler ); } } class BufferTimeSubscriber<T> extends Subscriber<T> { private buffers: Array<T[]> = []; constructor(destination: Subscriber<T[]>, private bufferTimeSpan: number, private bufferCreationInterval: number, private scheduler: Scheduler) { super(destination); const buffer = this.openBuffer(); if (bufferCreationInterval !== null && bufferCreationInterval >= 0) { const closeState = { subscriber: this, buffer }; const creationState = { bufferTimeSpan, bufferCreationInterval, subscriber: this, scheduler }; this.add(scheduler.schedule(dispatchBufferClose, bufferTimeSpan, closeState)); this.add(scheduler.schedule(dispatchBufferCreation, bufferCreationInterval, creationState)); } else { const timeSpanOnlyState = { subscriber: this, buffer, bufferTimeSpan }; this.add(scheduler.schedule(dispatchBufferTimeSpanOnly, bufferTimeSpan, timeSpanOnlyState)); } } protected _next(value: T) { const buffers = this.buffers; const len = buffers.length; for (let i = 0; i < len; i++) { buffers[i].push(value); } } protected _error(err: any) { this.buffers.length = 0; super._error(err); } protected _complete() { const { buffers, destination } = this; while (buffers.length > 0) { destination.next(buffers.shift()); } super._complete(); } _unsubscribe() { this.buffers = null; } openBuffer(): T[] { let buffer: T[] = []; this.buffers.push(buffer); return buffer; } closeBuffer(buffer: T[]) { this.destination.next(buffer); const buffers = this.buffers; buffers.splice(buffers.indexOf(buffer), 1); } } function dispatchBufferTimeSpanOnly(state: any) { const subscriber: BufferTimeSubscriber<any> = state.subscriber; const prevBuffer = state.buffer; Eif (prevBuffer) { subscriber.closeBuffer(prevBuffer); } state.buffer = subscriber.openBuffer(); Eif (!subscriber.isUnsubscribed) { (<any>this).schedule(state, state.bufferTimeSpan); } } function dispatchBufferCreation(state: any) { const { bufferCreationInterval, bufferTimeSpan, subscriber, scheduler } = state; const buffer = subscriber.openBuffer(); const action = <Action>this; Eif (!subscriber.isUnsubscribed) { action.add(scheduler.schedule(dispatchBufferClose, bufferTimeSpan, { subscriber, buffer })); action.schedule(state, bufferCreationInterval); } } function dispatchBufferClose({ subscriber, buffer }) { subscriber.closeBuffer(buffer); } |