Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

fromEventPattern.ts 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import { Observable } from '../Observable';
  2. import { isArray } from '../util/isArray';
  3. import { isFunction } from '../util/isFunction';
  4. import { NodeEventHandler } from './fromEvent';
  5. import { map } from '../operators/map';
  6. /* tslint:disable:max-line-length */
  7. export function fromEventPattern<T>(addHandler: (handler: NodeEventHandler) => any, removeHandler?: (handler: NodeEventHandler, signal?: any) => void): Observable<T>;
  8. /** @deprecated resultSelector no longer supported, pipe to map instead */
  9. export function fromEventPattern<T>(addHandler: (handler: NodeEventHandler) => any, removeHandler?: (handler: NodeEventHandler, signal?: any) => void, resultSelector?: (...args: any[]) => T): Observable<T>;
  10. /* tslint:enable:max-line-length */
  11. /**
  12. * Creates an Observable from an arbitrary API for registering event handlers.
  13. *
  14. * <span class="informal">When that method for adding event handler was something {@link fromEvent}
  15. * was not prepared for.</span>
  16. *
  17. * ![](fromEventPattern.png)
  18. *
  19. * `fromEventPattern` allows you to convert into an Observable any API that supports registering handler functions
  20. * for events. It is similar to {@link fromEvent}, but far
  21. * more flexible. In fact, all use cases of {@link fromEvent} could be easily handled by
  22. * `fromEventPattern` (although in slightly more verbose way).
  23. *
  24. * This operator accepts as a first argument an `addHandler` function, which will be injected with
  25. * handler parameter. That handler is actually an event handler function that you now can pass
  26. * to API expecting it. `addHandler` will be called whenever Observable
  27. * returned by the operator is subscribed, so registering handler in API will not
  28. * necessarily happen when `fromEventPattern` is called.
  29. *
  30. * After registration, every time an event that we listen to happens,
  31. * Observable returned by `fromEventPattern` will emit value that event handler
  32. * function was called with. Note that if event handler was called with more
  33. * then one argument, second and following arguments will not appear in the Observable.
  34. *
  35. * If API you are using allows to unregister event handlers as well, you can pass to `fromEventPattern`
  36. * another function - `removeHandler` - as a second parameter. It will be injected
  37. * with the same handler function as before, which now you can use to unregister
  38. * it from the API. `removeHandler` will be called when consumer of resulting Observable
  39. * unsubscribes from it.
  40. *
  41. * In some APIs unregistering is actually handled differently. Method registering an event handler
  42. * returns some kind of token, which is later used to identify which function should
  43. * be unregistered or it itself has method that unregisters event handler.
  44. * If that is the case with your API, make sure token returned
  45. * by registering method is returned by `addHandler`. Then it will be passed
  46. * as a second argument to `removeHandler`, where you will be able to use it.
  47. *
  48. * If you need access to all event handler parameters (not only the first one),
  49. * or you need to transform them in any way, you can call `fromEventPattern` with optional
  50. * third parameter - project function which will accept all arguments passed to
  51. * event handler when it is called. Whatever is returned from project function will appear on
  52. * resulting stream instead of usual event handlers first argument. This means
  53. * that default project can be thought of as function that takes its first parameter
  54. * and ignores the rest.
  55. *
  56. * ## Example
  57. * ### Emits clicks happening on the DOM document
  58. *
  59. * ```ts
  60. * import { fromEventPattern } from 'rxjs';
  61. *
  62. * function addClickHandler(handler) {
  63. * document.addEventListener('click', handler);
  64. * }
  65. *
  66. * function removeClickHandler(handler) {
  67. * document.removeEventListener('click', handler);
  68. * }
  69. *
  70. * const clicks = fromEventPattern(
  71. * addClickHandler,
  72. * removeClickHandler
  73. * );
  74. * clicks.subscribe(x => console.log(x));
  75. *
  76. * // Whenever you click anywhere in the browser, DOM MouseEvent
  77. * // object will be logged.
  78. * ```
  79. *
  80. * ## Example
  81. * ### Use with API that returns cancellation token
  82. *
  83. * ```ts
  84. * import { fromEventPattern } from 'rxjs';
  85. *
  86. * const token = someAPI.registerEventHandler(function() {});
  87. * someAPI.unregisterEventHandler(token); // this APIs cancellation method accepts
  88. * // not handler itself, but special token.
  89. *
  90. * const someAPIObservable = fromEventPattern(
  91. * function(handler) { return someAPI.registerEventHandler(handler); }, // Note that we return the token here...
  92. * function(handler, token) { someAPI.unregisterEventHandler(token); } // ...to then use it here.
  93. * );
  94. * ```
  95. *
  96. * ## Example
  97. * ### Use with project function
  98. *
  99. * ```ts
  100. * import { fromEventPattern } from 'rxjs';
  101. *
  102. * someAPI.registerEventHandler((eventType, eventMessage) => {
  103. * console.log(eventType, eventMessage); // Logs "EVENT_TYPE" "EVENT_MESSAGE" to console.
  104. * });
  105. *
  106. * const someAPIObservable = fromEventPattern(
  107. * handler => someAPI.registerEventHandler(handler),
  108. * handler => someAPI.unregisterEventHandler(handler)
  109. * (eventType, eventMessage) => eventType + " --- " + eventMessage // without that function only "EVENT_TYPE"
  110. * ); // would be emitted by the Observable
  111. *
  112. * someAPIObservable.subscribe(value => console.log(value));
  113. *
  114. * // Logs:
  115. * // "EVENT_TYPE --- EVENT_MESSAGE"
  116. * ```
  117. *
  118. * @see {@link fromEvent}
  119. * @see {@link bindCallback}
  120. * @see {@link bindNodeCallback}
  121. *
  122. * @param {function(handler: Function): any} addHandler A function that takes
  123. * a `handler` function as argument and attaches it somehow to the actual
  124. * source of events.
  125. * @param {function(handler: Function, token?: any): void} [removeHandler] A function that
  126. * takes a `handler` function as an argument and removes it from the event source. If `addHandler`
  127. * returns some kind of token, `removeHandler` function will have it as a second parameter.
  128. * @param {function(...args: any): T} [project] A function to
  129. * transform results. It takes the arguments from the event handler and
  130. * should return a single value.
  131. * @return {Observable<T>} Observable which, when an event happens, emits first parameter
  132. * passed to registered event handler. Alternatively it emits whatever project function returns
  133. * at that moment.
  134. * @static true
  135. * @name fromEventPattern
  136. * @owner Observable
  137. */
  138. export function fromEventPattern<T>(addHandler: (handler: NodeEventHandler) => any,
  139. removeHandler?: (handler: NodeEventHandler, signal?: any) => void,
  140. resultSelector?: (...args: any[]) => T): Observable<T | T[]> {
  141. if (resultSelector) {
  142. // DEPRECATED PATH
  143. return fromEventPattern<T>(addHandler, removeHandler).pipe(
  144. map(args => isArray(args) ? resultSelector(...args) : resultSelector(args))
  145. );
  146. }
  147. return new Observable<T | T[]>(subscriber => {
  148. const handler = (...e: T[]) => subscriber.next(e.length === 1 ? e[0] : e);
  149. let retValue: any;
  150. try {
  151. retValue = addHandler(handler);
  152. } catch (err) {
  153. subscriber.error(err);
  154. return undefined;
  155. }
  156. if (!isFunction(removeHandler)) {
  157. return undefined;
  158. }
  159. return () => removeHandler(handler, retValue) ;
  160. });
  161. }