mergeMap.js 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /** PURE_IMPORTS_START .._util_subscribeToResult,.._OuterSubscriber 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 { subscribeToResult } from '../util/subscribeToResult';
  10. import { OuterSubscriber } from '../OuterSubscriber';
  11. /* tslint:enable:max-line-length */
  12. /**
  13. * Projects each source value to an Observable which is merged in the output
  14. * Observable.
  15. *
  16. * <span class="informal">Maps each value to an Observable, then flattens all of
  17. * these inner Observables using {@link mergeAll}.</span>
  18. *
  19. * <img src="./img/mergeMap.png" width="100%">
  20. *
  21. * Returns an Observable that emits items based on applying a function that you
  22. * supply to each item emitted by the source Observable, where that function
  23. * returns an Observable, and then merging those resulting Observables and
  24. * emitting the results of this merger.
  25. *
  26. * @example <caption>Map and flatten each letter to an Observable ticking every 1 second</caption>
  27. * var letters = Rx.Observable.of('a', 'b', 'c');
  28. * var result = letters.mergeMap(x =>
  29. * Rx.Observable.interval(1000).map(i => x+i)
  30. * );
  31. * result.subscribe(x => console.log(x));
  32. *
  33. * // Results in the following:
  34. * // a0
  35. * // b0
  36. * // c0
  37. * // a1
  38. * // b1
  39. * // c1
  40. * // continues to list a,b,c with respective ascending integers
  41. *
  42. * @see {@link concatMap}
  43. * @see {@link exhaustMap}
  44. * @see {@link merge}
  45. * @see {@link mergeAll}
  46. * @see {@link mergeMapTo}
  47. * @see {@link mergeScan}
  48. * @see {@link switchMap}
  49. *
  50. * @param {function(value: T, ?index: number): ObservableInput} project A function
  51. * that, when applied to an item emitted by the source Observable, returns an
  52. * Observable.
  53. * @param {function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any} [resultSelector]
  54. * A function to produce the value on the output Observable based on the values
  55. * and the indices of the source (outer) emission and the inner Observable
  56. * emission. The arguments passed to this function are:
  57. * - `outerValue`: the value that came from the source
  58. * - `innerValue`: the value that came from the projected Observable
  59. * - `outerIndex`: the "index" of the value that came from the source
  60. * - `innerIndex`: the "index" of the value from the projected Observable
  61. * @param {number} [concurrent=Number.POSITIVE_INFINITY] Maximum number of input
  62. * Observables being subscribed to concurrently.
  63. * @return {Observable} An Observable that emits the result of applying the
  64. * projection function (and the optional `resultSelector`) to each item emitted
  65. * by the source Observable and merging the results of the Observables obtained
  66. * from this transformation.
  67. * @method mergeMap
  68. * @owner Observable
  69. */
  70. export function mergeMap(project, resultSelector, concurrent) {
  71. if (concurrent === void 0) {
  72. concurrent = Number.POSITIVE_INFINITY;
  73. }
  74. return function mergeMapOperatorFunction(source) {
  75. if (typeof resultSelector === 'number') {
  76. concurrent = resultSelector;
  77. resultSelector = null;
  78. }
  79. return source.lift(new MergeMapOperator(project, resultSelector, concurrent));
  80. };
  81. }
  82. export var MergeMapOperator = /*@__PURE__*/ (/*@__PURE__*/ function () {
  83. function MergeMapOperator(project, resultSelector, concurrent) {
  84. if (concurrent === void 0) {
  85. concurrent = Number.POSITIVE_INFINITY;
  86. }
  87. this.project = project;
  88. this.resultSelector = resultSelector;
  89. this.concurrent = concurrent;
  90. }
  91. MergeMapOperator.prototype.call = function (observer, source) {
  92. return source.subscribe(new MergeMapSubscriber(observer, this.project, this.resultSelector, this.concurrent));
  93. };
  94. return MergeMapOperator;
  95. }());
  96. /**
  97. * We need this JSDoc comment for affecting ESDoc.
  98. * @ignore
  99. * @extends {Ignored}
  100. */
  101. export var MergeMapSubscriber = /*@__PURE__*/ (/*@__PURE__*/ function (_super) {
  102. __extends(MergeMapSubscriber, _super);
  103. function MergeMapSubscriber(destination, project, resultSelector, concurrent) {
  104. if (concurrent === void 0) {
  105. concurrent = Number.POSITIVE_INFINITY;
  106. }
  107. _super.call(this, destination);
  108. this.project = project;
  109. this.resultSelector = resultSelector;
  110. this.concurrent = concurrent;
  111. this.hasCompleted = false;
  112. this.buffer = [];
  113. this.active = 0;
  114. this.index = 0;
  115. }
  116. MergeMapSubscriber.prototype._next = function (value) {
  117. if (this.active < this.concurrent) {
  118. this._tryNext(value);
  119. }
  120. else {
  121. this.buffer.push(value);
  122. }
  123. };
  124. MergeMapSubscriber.prototype._tryNext = function (value) {
  125. var result;
  126. var index = this.index++;
  127. try {
  128. result = this.project(value, index);
  129. }
  130. catch (err) {
  131. this.destination.error(err);
  132. return;
  133. }
  134. this.active++;
  135. this._innerSub(result, value, index);
  136. };
  137. MergeMapSubscriber.prototype._innerSub = function (ish, value, index) {
  138. this.add(subscribeToResult(this, ish, value, index));
  139. };
  140. MergeMapSubscriber.prototype._complete = function () {
  141. this.hasCompleted = true;
  142. if (this.active === 0 && this.buffer.length === 0) {
  143. this.destination.complete();
  144. }
  145. };
  146. MergeMapSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
  147. if (this.resultSelector) {
  148. this._notifyResultSelector(outerValue, innerValue, outerIndex, innerIndex);
  149. }
  150. else {
  151. this.destination.next(innerValue);
  152. }
  153. };
  154. MergeMapSubscriber.prototype._notifyResultSelector = function (outerValue, innerValue, outerIndex, innerIndex) {
  155. var result;
  156. try {
  157. result = this.resultSelector(outerValue, innerValue, outerIndex, innerIndex);
  158. }
  159. catch (err) {
  160. this.destination.error(err);
  161. return;
  162. }
  163. this.destination.next(result);
  164. };
  165. MergeMapSubscriber.prototype.notifyComplete = function (innerSub) {
  166. var buffer = this.buffer;
  167. this.remove(innerSub);
  168. this.active--;
  169. if (buffer.length > 0) {
  170. this._next(buffer.shift());
  171. }
  172. else if (this.active === 0 && this.hasCompleted) {
  173. this.destination.complete();
  174. }
  175. };
  176. return MergeMapSubscriber;
  177. }(OuterSubscriber));
  178. //# sourceMappingURL=mergeMap.js.map