FromEventPatternObservable.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { isFunction } from '../util/isFunction';
  2. import { Observable } from '../Observable';
  3. import { Subscription } from '../Subscription';
  4. /**
  5. * We need this JSDoc comment for affecting ESDoc.
  6. * @extends {Ignored}
  7. * @hide true
  8. */
  9. export class FromEventPatternObservable extends Observable {
  10. constructor(addHandler, removeHandler, selector) {
  11. super();
  12. this.addHandler = addHandler;
  13. this.removeHandler = removeHandler;
  14. this.selector = selector;
  15. }
  16. /**
  17. * Creates an Observable from an API based on addHandler/removeHandler
  18. * functions.
  19. *
  20. * <span class="informal">Converts any addHandler/removeHandler API to an
  21. * Observable.</span>
  22. *
  23. * <img src="./img/fromEventPattern.png" width="100%">
  24. *
  25. * Creates an Observable by using the `addHandler` and `removeHandler`
  26. * functions to add and remove the handlers, with an optional selector
  27. * function to project the event arguments to a result. The `addHandler` is
  28. * called when the output Observable is subscribed, and `removeHandler` is
  29. * called when the Subscription is unsubscribed.
  30. *
  31. * @example <caption>Emits clicks happening on the DOM document</caption>
  32. * function addClickHandler(handler) {
  33. * document.addEventListener('click', handler);
  34. * }
  35. *
  36. * function removeClickHandler(handler) {
  37. * document.removeEventListener('click', handler);
  38. * }
  39. *
  40. * var clicks = Rx.Observable.fromEventPattern(
  41. * addClickHandler,
  42. * removeClickHandler
  43. * );
  44. * clicks.subscribe(x => console.log(x));
  45. *
  46. * @see {@link from}
  47. * @see {@link fromEvent}
  48. *
  49. * @param {function(handler: Function): any} addHandler A function that takes
  50. * a `handler` function as argument and attaches it somehow to the actual
  51. * source of events.
  52. * @param {function(handler: Function, signal?: any): void} [removeHandler] An optional function that
  53. * takes a `handler` function as argument and removes it in case it was
  54. * previously attached using `addHandler`. if addHandler returns signal to teardown when remove,
  55. * removeHandler function will forward it.
  56. * @param {function(...args: any): T} [selector] An optional function to
  57. * post-process results. It takes the arguments from the event handler and
  58. * should return a single value.
  59. * @return {Observable<T>}
  60. * @static true
  61. * @name fromEventPattern
  62. * @owner Observable
  63. */
  64. static create(addHandler, removeHandler, selector) {
  65. return new FromEventPatternObservable(addHandler, removeHandler, selector);
  66. }
  67. /** @deprecated internal use only */ _subscribe(subscriber) {
  68. const removeHandler = this.removeHandler;
  69. const handler = !!this.selector ? (...args) => {
  70. this._callSelector(subscriber, args);
  71. } : function (e) { subscriber.next(e); };
  72. const retValue = this._callAddHandler(handler, subscriber);
  73. if (!isFunction(removeHandler)) {
  74. return;
  75. }
  76. subscriber.add(new Subscription(() => {
  77. //TODO: determine whether or not to forward to error handler
  78. removeHandler(handler, retValue);
  79. }));
  80. }
  81. _callSelector(subscriber, args) {
  82. try {
  83. const result = this.selector(...args);
  84. subscriber.next(result);
  85. }
  86. catch (e) {
  87. subscriber.error(e);
  88. }
  89. }
  90. _callAddHandler(handler, errorSubscriber) {
  91. try {
  92. return this.addHandler(handler) || null;
  93. }
  94. catch (e) {
  95. errorSubscriber.error(e);
  96. }
  97. }
  98. }
  99. //# sourceMappingURL=FromEventPatternObservable.js.map