ee1979a427eee03ec313a463cc6d34bab63c8530069b8c06b02204c88c6b99db6bdf1410624a7ee75c0ccc3269a43ddacea3daed01730f359284ca83535763 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { OperatorFunction } from '../types';
  2. import { operate } from '../util/lift';
  3. import { createOperatorSubscriber } from './OperatorSubscriber';
  4. /**
  5. * Groups pairs of consecutive emissions together and emits them as an array of
  6. * two values.
  7. *
  8. * <span class="informal">Puts the current value and previous value together as
  9. * an array, and emits that.</span>
  10. *
  11. * ![](pairwise.png)
  12. *
  13. * The Nth emission from the source Observable will cause the output Observable
  14. * to emit an array [(N-1)th, Nth] of the previous and the current value, as a
  15. * pair. For this reason, `pairwise` emits on the second and subsequent
  16. * emissions from the source Observable, but not on the first emission, because
  17. * there is no previous value in that case.
  18. *
  19. * ## Example
  20. *
  21. * On every click (starting from the second), emit the relative distance to the previous click
  22. *
  23. * ```ts
  24. * import { fromEvent, pairwise, map } from 'rxjs';
  25. *
  26. * const clicks = fromEvent<PointerEvent>(document, 'click');
  27. * const pairs = clicks.pipe(pairwise());
  28. * const distance = pairs.pipe(
  29. * map(([first, second]) => {
  30. * const x0 = first.clientX;
  31. * const y0 = first.clientY;
  32. * const x1 = second.clientX;
  33. * const y1 = second.clientY;
  34. * return Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2));
  35. * })
  36. * );
  37. *
  38. * distance.subscribe(x => console.log(x));
  39. * ```
  40. *
  41. * @see {@link buffer}
  42. * @see {@link bufferCount}
  43. *
  44. * @return A function that returns an Observable of pairs (as arrays) of
  45. * consecutive values from the source Observable.
  46. */
  47. export function pairwise<T>(): OperatorFunction<T, [T, T]> {
  48. return operate((source, subscriber) => {
  49. let prev: T;
  50. let hasPrev = false;
  51. source.subscribe(
  52. createOperatorSubscriber(subscriber, (value) => {
  53. const p = prev;
  54. prev = value;
  55. hasPrev && subscriber.next([p, value]);
  56. hasPrev = true;
  57. })
  58. );
  59. });
  60. }