Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bufferCount.ts 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import { Operator } from '../Operator';
  2. import { Subscriber } from '../Subscriber';
  3. import { Observable } from '../Observable';
  4. import { OperatorFunction, TeardownLogic } from '../types';
  5. /**
  6. * Buffers the source Observable values until the size hits the maximum
  7. * `bufferSize` given.
  8. *
  9. * <span class="informal">Collects values from the past as an array, and emits
  10. * that array only when its size reaches `bufferSize`.</span>
  11. *
  12. * ![](bufferCount.png)
  13. *
  14. * Buffers a number of values from the source Observable by `bufferSize` then
  15. * emits the buffer and clears it, and starts a new buffer each
  16. * `startBufferEvery` values. If `startBufferEvery` is not provided or is
  17. * `null`, then new buffers are started immediately at the start of the source
  18. * and when each buffer closes and is emitted.
  19. *
  20. * ## Examples
  21. *
  22. * Emit the last two click events as an array
  23. *
  24. * ```ts
  25. * import { fromEvent } from 'rxjs';
  26. * import { bufferCount } from 'rxjs/operators';
  27. *
  28. * const clicks = fromEvent(document, 'click');
  29. * const buffered = clicks.pipe(bufferCount(2));
  30. * buffered.subscribe(x => console.log(x));
  31. * ```
  32. *
  33. * On every click, emit the last two click events as an array
  34. *
  35. * ```ts
  36. * import { fromEvent } from 'rxjs';
  37. * import { bufferCount } from 'rxjs/operators';
  38. *
  39. * const clicks = fromEvent(document, 'click');
  40. * const buffered = clicks.pipe(bufferCount(2, 1));
  41. * buffered.subscribe(x => console.log(x));
  42. * ```
  43. *
  44. * @see {@link buffer}
  45. * @see {@link bufferTime}
  46. * @see {@link bufferToggle}
  47. * @see {@link bufferWhen}
  48. * @see {@link pairwise}
  49. * @see {@link windowCount}
  50. *
  51. * @param {number} bufferSize The maximum size of the buffer emitted.
  52. * @param {number} [startBufferEvery] Interval at which to start a new buffer.
  53. * For example if `startBufferEvery` is `2`, then a new buffer will be started
  54. * on every other value from the source. A new buffer is started at the
  55. * beginning of the source by default.
  56. * @return {Observable<T[]>} An Observable of arrays of buffered values.
  57. * @method bufferCount
  58. * @owner Observable
  59. */
  60. export function bufferCount<T>(bufferSize: number, startBufferEvery: number = null): OperatorFunction<T, T[]> {
  61. return function bufferCountOperatorFunction(source: Observable<T>) {
  62. return source.lift(new BufferCountOperator<T>(bufferSize, startBufferEvery));
  63. };
  64. }
  65. class BufferCountOperator<T> implements Operator<T, T[]> {
  66. private subscriberClass: any;
  67. constructor(private bufferSize: number, private startBufferEvery: number) {
  68. if (!startBufferEvery || bufferSize === startBufferEvery) {
  69. this.subscriberClass = BufferCountSubscriber;
  70. } else {
  71. this.subscriberClass = BufferSkipCountSubscriber;
  72. }
  73. }
  74. call(subscriber: Subscriber<T[]>, source: any): TeardownLogic {
  75. return source.subscribe(new this.subscriberClass(subscriber, this.bufferSize, this.startBufferEvery));
  76. }
  77. }
  78. /**
  79. * We need this JSDoc comment for affecting ESDoc.
  80. * @ignore
  81. * @extends {Ignored}
  82. */
  83. class BufferCountSubscriber<T> extends Subscriber<T> {
  84. private buffer: T[] = [];
  85. constructor(destination: Subscriber<T[]>, private bufferSize: number) {
  86. super(destination);
  87. }
  88. protected _next(value: T): void {
  89. const buffer = this.buffer;
  90. buffer.push(value);
  91. if (buffer.length == this.bufferSize) {
  92. this.destination.next(buffer);
  93. this.buffer = [];
  94. }
  95. }
  96. protected _complete(): void {
  97. const buffer = this.buffer;
  98. if (buffer.length > 0) {
  99. this.destination.next(buffer);
  100. }
  101. super._complete();
  102. }
  103. }
  104. /**
  105. * We need this JSDoc comment for affecting ESDoc.
  106. * @ignore
  107. * @extends {Ignored}
  108. */
  109. class BufferSkipCountSubscriber<T> extends Subscriber<T> {
  110. private buffers: Array<T[]> = [];
  111. private count: number = 0;
  112. constructor(destination: Subscriber<T[]>, private bufferSize: number, private startBufferEvery: number) {
  113. super(destination);
  114. }
  115. protected _next(value: T): void {
  116. const { bufferSize, startBufferEvery, buffers, count } = this;
  117. this.count++;
  118. if (count % startBufferEvery === 0) {
  119. buffers.push([]);
  120. }
  121. for (let i = buffers.length; i--; ) {
  122. const buffer = buffers[i];
  123. buffer.push(value);
  124. if (buffer.length === bufferSize) {
  125. buffers.splice(i, 1);
  126. this.destination.next(buffer);
  127. }
  128. }
  129. }
  130. protected _complete(): void {
  131. const { buffers, destination } = this;
  132. while (buffers.length > 0) {
  133. let buffer = buffers.shift();
  134. if (buffer.length > 0) {
  135. destination.next(buffer);
  136. }
  137. }
  138. super._complete();
  139. }
  140. }