combineLatest.js 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /** PURE_IMPORTS_START .._observable_ArrayObservable,.._util_isArray,.._OuterSubscriber,.._util_subscribeToResult 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 { ArrayObservable } from '../observable/ArrayObservable';
  10. import { isArray } from '../util/isArray';
  11. import { OuterSubscriber } from '../OuterSubscriber';
  12. import { subscribeToResult } from '../util/subscribeToResult';
  13. var none = {};
  14. /* tslint:enable:max-line-length */
  15. /**
  16. * Combines multiple Observables to create an Observable whose values are
  17. * calculated from the latest values of each of its input Observables.
  18. *
  19. * <span class="informal">Whenever any input Observable emits a value, it
  20. * computes a formula using the latest values from all the inputs, then emits
  21. * the output of that formula.</span>
  22. *
  23. * <img src="./img/combineLatest.png" width="100%">
  24. *
  25. * `combineLatest` combines the values from this Observable with values from
  26. * Observables passed as arguments. This is done by subscribing to each
  27. * Observable, in order, and collecting an array of each of the most recent
  28. * values any time any of the input Observables emits, then either taking that
  29. * array and passing it as arguments to an optional `project` function and
  30. * emitting the return value of that, or just emitting the array of recent
  31. * values directly if there is no `project` function.
  32. *
  33. * @example <caption>Dynamically calculate the Body-Mass Index from an Observable of weight and one for height</caption>
  34. * var weight = Rx.Observable.of(70, 72, 76, 79, 75);
  35. * var height = Rx.Observable.of(1.76, 1.77, 1.78);
  36. * var bmi = weight.combineLatest(height, (w, h) => w / (h * h));
  37. * bmi.subscribe(x => console.log('BMI is ' + x));
  38. *
  39. * // With output to console:
  40. * // BMI is 24.212293388429753
  41. * // BMI is 23.93948099205209
  42. * // BMI is 23.671253629592222
  43. *
  44. * @see {@link combineAll}
  45. * @see {@link merge}
  46. * @see {@link withLatestFrom}
  47. *
  48. * @param {ObservableInput} other An input Observable to combine with the source
  49. * Observable. More than one input Observables may be given as argument.
  50. * @param {function} [project] An optional function to project the values from
  51. * the combined latest values into a new value on the output Observable.
  52. * @return {Observable} An Observable of projected values from the most recent
  53. * values from each input Observable, or an array of the most recent values from
  54. * each input Observable.
  55. * @method combineLatest
  56. * @owner Observable
  57. */
  58. export function combineLatest() {
  59. var observables = [];
  60. for (var _i = 0; _i < arguments.length; _i++) {
  61. observables[_i - 0] = arguments[_i];
  62. }
  63. var project = null;
  64. if (typeof observables[observables.length - 1] === 'function') {
  65. project = observables.pop();
  66. }
  67. // if the first and only other argument besides the resultSelector is an array
  68. // assume it's been called with `combineLatest([obs1, obs2, obs3], project)`
  69. if (observables.length === 1 && isArray(observables[0])) {
  70. observables = observables[0].slice();
  71. }
  72. return function (source) { return source.lift.call(new ArrayObservable([source].concat(observables)), new CombineLatestOperator(project)); };
  73. }
  74. export var CombineLatestOperator = /*@__PURE__*/ (/*@__PURE__*/ function () {
  75. function CombineLatestOperator(project) {
  76. this.project = project;
  77. }
  78. CombineLatestOperator.prototype.call = function (subscriber, source) {
  79. return source.subscribe(new CombineLatestSubscriber(subscriber, this.project));
  80. };
  81. return CombineLatestOperator;
  82. }());
  83. /**
  84. * We need this JSDoc comment for affecting ESDoc.
  85. * @ignore
  86. * @extends {Ignored}
  87. */
  88. export var CombineLatestSubscriber = /*@__PURE__*/ (/*@__PURE__*/ function (_super) {
  89. __extends(CombineLatestSubscriber, _super);
  90. function CombineLatestSubscriber(destination, project) {
  91. _super.call(this, destination);
  92. this.project = project;
  93. this.active = 0;
  94. this.values = [];
  95. this.observables = [];
  96. }
  97. CombineLatestSubscriber.prototype._next = function (observable) {
  98. this.values.push(none);
  99. this.observables.push(observable);
  100. };
  101. CombineLatestSubscriber.prototype._complete = function () {
  102. var observables = this.observables;
  103. var len = observables.length;
  104. if (len === 0) {
  105. this.destination.complete();
  106. }
  107. else {
  108. this.active = len;
  109. this.toRespond = len;
  110. for (var i = 0; i < len; i++) {
  111. var observable = observables[i];
  112. this.add(subscribeToResult(this, observable, observable, i));
  113. }
  114. }
  115. };
  116. CombineLatestSubscriber.prototype.notifyComplete = function (unused) {
  117. if ((this.active -= 1) === 0) {
  118. this.destination.complete();
  119. }
  120. };
  121. CombineLatestSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
  122. var values = this.values;
  123. var oldVal = values[outerIndex];
  124. var toRespond = !this.toRespond
  125. ? 0
  126. : oldVal === none ? --this.toRespond : this.toRespond;
  127. values[outerIndex] = innerValue;
  128. if (toRespond === 0) {
  129. if (this.project) {
  130. this._tryProject(values);
  131. }
  132. else {
  133. this.destination.next(values.slice());
  134. }
  135. }
  136. };
  137. CombineLatestSubscriber.prototype._tryProject = function (values) {
  138. var result;
  139. try {
  140. result = this.project.apply(this, values);
  141. }
  142. catch (err) {
  143. this.destination.error(err);
  144. return;
  145. }
  146. this.destination.next(result);
  147. };
  148. return CombineLatestSubscriber;
  149. }(OuterSubscriber));
  150. //# sourceMappingURL=combineLatest.js.map