delayWhen.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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 Subscriber_1 = require('../Subscriber');
  8. var Observable_1 = require('../Observable');
  9. var OuterSubscriber_1 = require('../OuterSubscriber');
  10. var subscribeToResult_1 = require('../util/subscribeToResult');
  11. /**
  12. * Delays the emission of items from the source Observable by a given time span
  13. * determined by the emissions of another Observable.
  14. *
  15. * <span class="informal">It's like {@link delay}, but the time span of the
  16. * delay duration is determined by a second Observable.</span>
  17. *
  18. * <img src="./img/delayWhen.png" width="100%">
  19. *
  20. * `delayWhen` time shifts each emitted value from the source Observable by a
  21. * time span determined by another Observable. When the source emits a value,
  22. * the `delayDurationSelector` function is called with the source value as
  23. * argument, and should return an Observable, called the "duration" Observable.
  24. * The source value is emitted on the output Observable only when the duration
  25. * Observable emits a value or completes.
  26. *
  27. * Optionally, `delayWhen` takes a second argument, `subscriptionDelay`, which
  28. * is an Observable. When `subscriptionDelay` emits its first value or
  29. * completes, the source Observable is subscribed to and starts behaving like
  30. * described in the previous paragraph. If `subscriptionDelay` is not provided,
  31. * `delayWhen` will subscribe to the source Observable as soon as the output
  32. * Observable is subscribed.
  33. *
  34. * @example <caption>Delay each click by a random amount of time, between 0 and 5 seconds</caption>
  35. * var clicks = Rx.Observable.fromEvent(document, 'click');
  36. * var delayedClicks = clicks.delayWhen(event =>
  37. * Rx.Observable.interval(Math.random() * 5000)
  38. * );
  39. * delayedClicks.subscribe(x => console.log(x));
  40. *
  41. * @see {@link debounce}
  42. * @see {@link delay}
  43. *
  44. * @param {function(value: T): Observable} delayDurationSelector A function that
  45. * returns an Observable for each value emitted by the source Observable, which
  46. * is then used to delay the emission of that item on the output Observable
  47. * until the Observable returned from this function emits a value.
  48. * @param {Observable} subscriptionDelay An Observable that triggers the
  49. * subscription to the source Observable once it emits any value.
  50. * @return {Observable} An Observable that delays the emissions of the source
  51. * Observable by an amount of time specified by the Observable returned by
  52. * `delayDurationSelector`.
  53. * @method delayWhen
  54. * @owner Observable
  55. */
  56. function delayWhen(delayDurationSelector, subscriptionDelay) {
  57. if (subscriptionDelay) {
  58. return function (source) {
  59. return new SubscriptionDelayObservable(source, subscriptionDelay)
  60. .lift(new DelayWhenOperator(delayDurationSelector));
  61. };
  62. }
  63. return function (source) { return source.lift(new DelayWhenOperator(delayDurationSelector)); };
  64. }
  65. exports.delayWhen = delayWhen;
  66. var DelayWhenOperator = (function () {
  67. function DelayWhenOperator(delayDurationSelector) {
  68. this.delayDurationSelector = delayDurationSelector;
  69. }
  70. DelayWhenOperator.prototype.call = function (subscriber, source) {
  71. return source.subscribe(new DelayWhenSubscriber(subscriber, this.delayDurationSelector));
  72. };
  73. return DelayWhenOperator;
  74. }());
  75. /**
  76. * We need this JSDoc comment for affecting ESDoc.
  77. * @ignore
  78. * @extends {Ignored}
  79. */
  80. var DelayWhenSubscriber = (function (_super) {
  81. __extends(DelayWhenSubscriber, _super);
  82. function DelayWhenSubscriber(destination, delayDurationSelector) {
  83. _super.call(this, destination);
  84. this.delayDurationSelector = delayDurationSelector;
  85. this.completed = false;
  86. this.delayNotifierSubscriptions = [];
  87. this.values = [];
  88. }
  89. DelayWhenSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
  90. this.destination.next(outerValue);
  91. this.removeSubscription(innerSub);
  92. this.tryComplete();
  93. };
  94. DelayWhenSubscriber.prototype.notifyError = function (error, innerSub) {
  95. this._error(error);
  96. };
  97. DelayWhenSubscriber.prototype.notifyComplete = function (innerSub) {
  98. var value = this.removeSubscription(innerSub);
  99. if (value) {
  100. this.destination.next(value);
  101. }
  102. this.tryComplete();
  103. };
  104. DelayWhenSubscriber.prototype._next = function (value) {
  105. try {
  106. var delayNotifier = this.delayDurationSelector(value);
  107. if (delayNotifier) {
  108. this.tryDelay(delayNotifier, value);
  109. }
  110. }
  111. catch (err) {
  112. this.destination.error(err);
  113. }
  114. };
  115. DelayWhenSubscriber.prototype._complete = function () {
  116. this.completed = true;
  117. this.tryComplete();
  118. };
  119. DelayWhenSubscriber.prototype.removeSubscription = function (subscription) {
  120. subscription.unsubscribe();
  121. var subscriptionIdx = this.delayNotifierSubscriptions.indexOf(subscription);
  122. var value = null;
  123. if (subscriptionIdx !== -1) {
  124. value = this.values[subscriptionIdx];
  125. this.delayNotifierSubscriptions.splice(subscriptionIdx, 1);
  126. this.values.splice(subscriptionIdx, 1);
  127. }
  128. return value;
  129. };
  130. DelayWhenSubscriber.prototype.tryDelay = function (delayNotifier, value) {
  131. var notifierSubscription = subscribeToResult_1.subscribeToResult(this, delayNotifier, value);
  132. if (notifierSubscription && !notifierSubscription.closed) {
  133. this.add(notifierSubscription);
  134. this.delayNotifierSubscriptions.push(notifierSubscription);
  135. }
  136. this.values.push(value);
  137. };
  138. DelayWhenSubscriber.prototype.tryComplete = function () {
  139. if (this.completed && this.delayNotifierSubscriptions.length === 0) {
  140. this.destination.complete();
  141. }
  142. };
  143. return DelayWhenSubscriber;
  144. }(OuterSubscriber_1.OuterSubscriber));
  145. /**
  146. * We need this JSDoc comment for affecting ESDoc.
  147. * @ignore
  148. * @extends {Ignored}
  149. */
  150. var SubscriptionDelayObservable = (function (_super) {
  151. __extends(SubscriptionDelayObservable, _super);
  152. function SubscriptionDelayObservable(/** @deprecated internal use only */ source, subscriptionDelay) {
  153. _super.call(this);
  154. this.source = source;
  155. this.subscriptionDelay = subscriptionDelay;
  156. }
  157. /** @deprecated internal use only */ SubscriptionDelayObservable.prototype._subscribe = function (subscriber) {
  158. this.subscriptionDelay.subscribe(new SubscriptionDelaySubscriber(subscriber, this.source));
  159. };
  160. return SubscriptionDelayObservable;
  161. }(Observable_1.Observable));
  162. /**
  163. * We need this JSDoc comment for affecting ESDoc.
  164. * @ignore
  165. * @extends {Ignored}
  166. */
  167. var SubscriptionDelaySubscriber = (function (_super) {
  168. __extends(SubscriptionDelaySubscriber, _super);
  169. function SubscriptionDelaySubscriber(parent, source) {
  170. _super.call(this);
  171. this.parent = parent;
  172. this.source = source;
  173. this.sourceSubscribed = false;
  174. }
  175. SubscriptionDelaySubscriber.prototype._next = function (unused) {
  176. this.subscribeToSource();
  177. };
  178. SubscriptionDelaySubscriber.prototype._error = function (err) {
  179. this.unsubscribe();
  180. this.parent.error(err);
  181. };
  182. SubscriptionDelaySubscriber.prototype._complete = function () {
  183. this.subscribeToSource();
  184. };
  185. SubscriptionDelaySubscriber.prototype.subscribeToSource = function () {
  186. if (!this.sourceSubscribed) {
  187. this.sourceSubscribed = true;
  188. this.unsubscribe();
  189. this.source.subscribe(this.parent);
  190. }
  191. };
  192. return SubscriptionDelaySubscriber;
  193. }(Subscriber_1.Subscriber));
  194. //# sourceMappingURL=delayWhen.js.map