tap.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import { Subscriber } from '../Subscriber';
  2. /* tslint:enable:max-line-length */
  3. /**
  4. * Perform a side effect for every emission on the source Observable, but return
  5. * an Observable that is identical to the source.
  6. *
  7. * <span class="informal">Intercepts each emission on the source and runs a
  8. * function, but returns an output which is identical to the source as long as errors don't occur.</span>
  9. *
  10. * <img src="./img/do.png" width="100%">
  11. *
  12. * Returns a mirrored Observable of the source Observable, but modified so that
  13. * the provided Observer is called to perform a side effect for every value,
  14. * error, and completion emitted by the source. Any errors that are thrown in
  15. * the aforementioned Observer or handlers are safely sent down the error path
  16. * of the output Observable.
  17. *
  18. * This operator is useful for debugging your Observables for the correct values
  19. * or performing other side effects.
  20. *
  21. * Note: this is different to a `subscribe` on the Observable. If the Observable
  22. * returned by `do` is not subscribed, the side effects specified by the
  23. * Observer will never happen. `do` therefore simply spies on existing
  24. * execution, it does not trigger an execution to happen like `subscribe` does.
  25. *
  26. * @example <caption>Map every click to the clientX position of that click, while also logging the click event</caption>
  27. * var clicks = Rx.Observable.fromEvent(document, 'click');
  28. * var positions = clicks
  29. * .do(ev => console.log(ev))
  30. * .map(ev => ev.clientX);
  31. * positions.subscribe(x => console.log(x));
  32. *
  33. * @see {@link map}
  34. * @see {@link subscribe}
  35. *
  36. * @param {Observer|function} [nextOrObserver] A normal Observer object or a
  37. * callback for `next`.
  38. * @param {function} [error] Callback for errors in the source.
  39. * @param {function} [complete] Callback for the completion of the source.
  40. * @return {Observable} An Observable identical to the source, but runs the
  41. * specified Observer or callback(s) for each item.
  42. * @name tap
  43. */
  44. export function tap(nextOrObserver, error, complete) {
  45. return function tapOperatorFunction(source) {
  46. return source.lift(new DoOperator(nextOrObserver, error, complete));
  47. };
  48. }
  49. class DoOperator {
  50. constructor(nextOrObserver, error, complete) {
  51. this.nextOrObserver = nextOrObserver;
  52. this.error = error;
  53. this.complete = complete;
  54. }
  55. call(subscriber, source) {
  56. return source.subscribe(new DoSubscriber(subscriber, this.nextOrObserver, this.error, this.complete));
  57. }
  58. }
  59. /**
  60. * We need this JSDoc comment for affecting ESDoc.
  61. * @ignore
  62. * @extends {Ignored}
  63. */
  64. class DoSubscriber extends Subscriber {
  65. constructor(destination, nextOrObserver, error, complete) {
  66. super(destination);
  67. const safeSubscriber = new Subscriber(nextOrObserver, error, complete);
  68. safeSubscriber.syncErrorThrowable = true;
  69. this.add(safeSubscriber);
  70. this.safeSubscriber = safeSubscriber;
  71. }
  72. _next(value) {
  73. const { safeSubscriber } = this;
  74. safeSubscriber.next(value);
  75. if (safeSubscriber.syncErrorThrown) {
  76. this.destination.error(safeSubscriber.syncErrorValue);
  77. }
  78. else {
  79. this.destination.next(value);
  80. }
  81. }
  82. _error(err) {
  83. const { safeSubscriber } = this;
  84. safeSubscriber.error(err);
  85. if (safeSubscriber.syncErrorThrown) {
  86. this.destination.error(safeSubscriber.syncErrorValue);
  87. }
  88. else {
  89. this.destination.error(err);
  90. }
  91. }
  92. _complete() {
  93. const { safeSubscriber } = this;
  94. safeSubscriber.complete();
  95. if (safeSubscriber.syncErrorThrown) {
  96. this.destination.error(safeSubscriber.syncErrorValue);
  97. }
  98. else {
  99. this.destination.complete();
  100. }
  101. }
  102. }
  103. //# sourceMappingURL=tap.js.map