distinct.js 4.7 KB

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