distinct.js 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /** PURE_IMPORTS_START .._OuterSubscriber,.._util_subscribeToResult,.._util_Set PURE_IMPORTS_END */
  2. var __extends = (this && this.__extends) || function (d, b) {
  3. for (var p in b)
  4. if (b.hasOwnProperty(p))
  5. d[p] = b[p];
  6. function __() { this.constructor = d; }
  7. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  8. };
  9. import { OuterSubscriber } from '../OuterSubscriber';
  10. import { subscribeToResult } from '../util/subscribeToResult';
  11. import { Set } from '../util/Set';
  12. /**
  13. * Returns an Observable that emits all items emitted by the source Observable that are distinct by comparison from previous items.
  14. *
  15. * If a keySelector function is provided, then it will project each value from the source observable into a new value that it will
  16. * check for equality with previously projected values. If a keySelector function is not provided, it will use each value from the
  17. * source observable directly with an equality check against previous values.
  18. *
  19. * In JavaScript runtimes that support `Set`, this operator will use a `Set` to improve performance of the distinct value checking.
  20. *
  21. * In other runtimes, this operator will use a minimal implementation of `Set` that relies on an `Array` and `indexOf` under the
  22. * hood, so performance will degrade as more values are checked for distinction. Even in newer browsers, a long-running `distinct`
  23. * use might result in memory leaks. To help alleviate this in some scenarios, an optional `flushes` parameter is also provided so
  24. * that the internal `Set` can be "flushed", basically clearing it of values.
  25. *
  26. * @example <caption>A simple example with numbers</caption>
  27. * Observable.of(1, 1, 2, 2, 2, 1, 2, 3, 4, 3, 2, 1)
  28. * .distinct()
  29. * .subscribe(x => console.log(x)); // 1, 2, 3, 4
  30. *
  31. * @example <caption>An example using a keySelector function</caption>
  32. * interface Person {
  33. * age: number,
  34. * name: string
  35. * }
  36. *
  37. * Observable.of<Person>(
  38. * { age: 4, name: 'Foo'},
  39. * { age: 7, name: 'Bar'},
  40. * { age: 5, name: 'Foo'})
  41. * .distinct((p: Person) => p.name)
  42. * .subscribe(x => console.log(x));
  43. *
  44. * // displays:
  45. * // { age: 4, name: 'Foo' }
  46. * // { age: 7, name: 'Bar' }
  47. *
  48. * @see {@link distinctUntilChanged}
  49. * @see {@link distinctUntilKeyChanged}
  50. *
  51. * @param {function} [keySelector] Optional function to select which value you want to check as distinct.
  52. * @param {Observable} [flushes] Optional Observable for flushing the internal HashSet of the operator.
  53. * @return {Observable} An Observable that emits items from the source Observable with distinct values.
  54. * @method distinct
  55. * @owner Observable
  56. */
  57. export function distinct(keySelector, flushes) {
  58. return function (source) { return source.lift(new DistinctOperator(keySelector, flushes)); };
  59. }
  60. var DistinctOperator = /*@__PURE__*/ (/*@__PURE__*/ function () {
  61. function DistinctOperator(keySelector, flushes) {
  62. this.keySelector = keySelector;
  63. this.flushes = flushes;
  64. }
  65. DistinctOperator.prototype.call = function (subscriber, source) {
  66. return source.subscribe(new DistinctSubscriber(subscriber, this.keySelector, this.flushes));
  67. };
  68. return DistinctOperator;
  69. }());
  70. /**
  71. * We need this JSDoc comment for affecting ESDoc.
  72. * @ignore
  73. * @extends {Ignored}
  74. */
  75. export var DistinctSubscriber = /*@__PURE__*/ (/*@__PURE__*/ function (_super) {
  76. __extends(DistinctSubscriber, _super);
  77. function DistinctSubscriber(destination, keySelector, flushes) {
  78. _super.call(this, destination);
  79. this.keySelector = keySelector;
  80. this.values = new Set();
  81. if (flushes) {
  82. this.add(subscribeToResult(this, flushes));
  83. }
  84. }
  85. DistinctSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
  86. this.values.clear();
  87. };
  88. DistinctSubscriber.prototype.notifyError = function (error, innerSub) {
  89. this._error(error);
  90. };
  91. DistinctSubscriber.prototype._next = function (value) {
  92. if (this.keySelector) {
  93. this._useKeySelector(value);
  94. }
  95. else {
  96. this._finalizeNext(value, value);
  97. }
  98. };
  99. DistinctSubscriber.prototype._useKeySelector = function (value) {
  100. var key;
  101. var destination = this.destination;
  102. try {
  103. key = this.keySelector(value);
  104. }
  105. catch (err) {
  106. destination.error(err);
  107. return;
  108. }
  109. this._finalizeNext(key, value);
  110. };
  111. DistinctSubscriber.prototype._finalizeNext = function (key, value) {
  112. var values = this.values;
  113. if (!values.has(key)) {
  114. values.add(key);
  115. this.destination.next(value);
  116. }
  117. };
  118. return DistinctSubscriber;
  119. }(OuterSubscriber));
  120. //# sourceMappingURL=distinct.js.map