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

bindNodeCallback.ts 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import { Observable } from '../Observable';
  2. import { AsyncSubject } from '../AsyncSubject';
  3. import { Subscriber } from '../Subscriber';
  4. import { SchedulerAction, SchedulerLike } from '../types';
  5. import { map } from '../operators/map';
  6. import { canReportError } from '../util/canReportError';
  7. import { isScheduler } from '../util/isScheduler';
  8. import { isArray } from '../util/isArray';
  9. /* tslint:disable:max-line-length */
  10. /** @deprecated resultSelector is deprecated, pipe to map instead */
  11. export function bindNodeCallback(callbackFunc: Function, resultSelector: Function, scheduler?: SchedulerLike): (...args: any[]) => Observable<any>;
  12. export function bindNodeCallback<R1, R2, R3, R4>(callbackFunc: (callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
  13. export function bindNodeCallback<R1, R2, R3>(callbackFunc: (callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): () => Observable<[R1, R2, R3]>;
  14. export function bindNodeCallback<R1, R2>(callbackFunc: (callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): () => Observable<[R1, R2]>;
  15. export function bindNodeCallback<R1>(callbackFunc: (callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): () => Observable<R1>;
  16. export function bindNodeCallback(callbackFunc: (callback: (err: any) => any) => any, scheduler?: SchedulerLike): () => Observable<void>;
  17. export function bindNodeCallback<A1, R1, R2, R3, R4>(callbackFunc: (arg1: A1, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
  18. export function bindNodeCallback<A1, R1, R2, R3>(callbackFunc: (arg1: A1, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<[R1, R2, R3]>;
  19. export function bindNodeCallback<A1, R1, R2>(callbackFunc: (arg1: A1, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<[R1, R2]>;
  20. export function bindNodeCallback<A1, R1>(callbackFunc: (arg1: A1, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<R1>;
  21. export function bindNodeCallback<A1>(callbackFunc: (arg1: A1, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<void>;
  22. export function bindNodeCallback<A1, A2, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
  23. export function bindNodeCallback<A1, A2, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<[R1, R2, R3]>;
  24. export function bindNodeCallback<A1, A2, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<[R1, R2]>;
  25. export function bindNodeCallback<A1, A2, R1>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<R1>;
  26. export function bindNodeCallback<A1, A2>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<void>;
  27. export function bindNodeCallback<A1, A2, A3, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
  28. export function bindNodeCallback<A1, A2, A3, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<[R1, R2, R3]>;
  29. export function bindNodeCallback<A1, A2, A3, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<[R1, R2]>;
  30. export function bindNodeCallback<A1, A2, A3, R1>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<R1>;
  31. export function bindNodeCallback<A1, A2, A3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<void>;
  32. export function bindNodeCallback<A1, A2, A3, A4, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
  33. export function bindNodeCallback<A1, A2, A3, A4, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<[R1, R2, R3]>;
  34. export function bindNodeCallback<A1, A2, A3, A4, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<[R1, R2]>;
  35. export function bindNodeCallback<A1, A2, A3, A4, R1>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<R1>;
  36. export function bindNodeCallback<A1, A2, A3, A4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<void>;
  37. export function bindNodeCallback<A1, A2, A3, A4, A5, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
  38. export function bindNodeCallback<A1, A2, A3, A4, A5, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<[R1, R2, R3]>;
  39. export function bindNodeCallback<A1, A2, A3, A4, A5, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<[R1, R2]>;
  40. export function bindNodeCallback<A1, A2, A3, A4, A5, R1>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<R1>;
  41. export function bindNodeCallback<A1, A2, A3, A4, A5>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<void>; /* tslint:enable:max-line-length */
  42. export function bindNodeCallback(callbackFunc: Function, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
  43. /**
  44. * Converts a Node.js-style callback API to a function that returns an
  45. * Observable.
  46. *
  47. * <span class="informal">It's just like {@link bindCallback}, but the
  48. * callback is expected to be of type `callback(error, result)`.</span>
  49. *
  50. * `bindNodeCallback` is not an operator because its input and output are not
  51. * Observables. The input is a function `func` with some parameters, but the
  52. * last parameter must be a callback function that `func` calls when it is
  53. * done. The callback function is expected to follow Node.js conventions,
  54. * where the first argument to the callback is an error object, signaling
  55. * whether call was successful. If that object is passed to callback, it means
  56. * something went wrong.
  57. *
  58. * The output of `bindNodeCallback` is a function that takes the same
  59. * parameters as `func`, except the last one (the callback). When the output
  60. * function is called with arguments, it will return an Observable.
  61. * If `func` calls its callback with error parameter present, Observable will
  62. * error with that value as well. If error parameter is not passed, Observable will emit
  63. * second parameter. If there are more parameters (third and so on),
  64. * Observable will emit an array with all arguments, except first error argument.
  65. *
  66. * Note that `func` will not be called at the same time output function is,
  67. * but rather whenever resulting Observable is subscribed. By default call to
  68. * `func` will happen synchronously after subscription, but that can be changed
  69. * with proper `scheduler` provided as optional third parameter. {@link SchedulerLike}
  70. * can also control when values from callback will be emitted by Observable.
  71. * To find out more, check out documentation for {@link bindCallback}, where
  72. * {@link SchedulerLike} works exactly the same.
  73. *
  74. * As in {@link bindCallback}, context (`this` property) of input function will be set to context
  75. * of returned function, when it is called.
  76. *
  77. * After Observable emits value, it will complete immediately. This means
  78. * even if `func` calls callback again, values from second and consecutive
  79. * calls will never appear on the stream. If you need to handle functions
  80. * that call callbacks multiple times, check out {@link fromEvent} or
  81. * {@link fromEventPattern} instead.
  82. *
  83. * Note that `bindNodeCallback` can be used in non-Node.js environments as well.
  84. * "Node.js-style" callbacks are just a convention, so if you write for
  85. * browsers or any other environment and API you use implements that callback style,
  86. * `bindNodeCallback` can be safely used on that API functions as well.
  87. *
  88. * Remember that Error object passed to callback does not have to be an instance
  89. * of JavaScript built-in `Error` object. In fact, it does not even have to an object.
  90. * Error parameter of callback function is interpreted as "present", when value
  91. * of that parameter is truthy. It could be, for example, non-zero number, non-empty
  92. * string or boolean `true`. In all of these cases resulting Observable would error
  93. * with that value. This means usually regular style callbacks will fail very often when
  94. * `bindNodeCallback` is used. If your Observable errors much more often then you
  95. * would expect, check if callback really is called in Node.js-style and, if not,
  96. * switch to {@link bindCallback} instead.
  97. *
  98. * Note that even if error parameter is technically present in callback, but its value
  99. * is falsy, it still won't appear in array emitted by Observable.
  100. *
  101. * ## Examples
  102. * ### Read a file from the filesystem and get the data as an Observable
  103. * ```ts
  104. * import * as fs from 'fs';
  105. * const readFileAsObservable = bindNodeCallback(fs.readFile);
  106. * const result = readFileAsObservable('./roadNames.txt', 'utf8');
  107. * result.subscribe(x => console.log(x), e => console.error(e));
  108. * ```
  109. *
  110. * ### Use on function calling callback with multiple arguments
  111. * ```ts
  112. * someFunction((err, a, b) => {
  113. * console.log(err); // null
  114. * console.log(a); // 5
  115. * console.log(b); // "some string"
  116. * });
  117. * const boundSomeFunction = bindNodeCallback(someFunction);
  118. * boundSomeFunction()
  119. * .subscribe(value => {
  120. * console.log(value); // [5, "some string"]
  121. * });
  122. * ```
  123. *
  124. * ### Use on function calling callback in regular style
  125. * ```ts
  126. * someFunction(a => {
  127. * console.log(a); // 5
  128. * });
  129. * const boundSomeFunction = bindNodeCallback(someFunction);
  130. * boundSomeFunction()
  131. * .subscribe(
  132. * value => {} // never gets called
  133. * err => console.log(err) // 5
  134. * );
  135. * ```
  136. *
  137. * @see {@link bindCallback}
  138. * @see {@link from}
  139. *
  140. * @param {function} func Function with a Node.js-style callback as the last parameter.
  141. * @param {SchedulerLike} [scheduler] The scheduler on which to schedule the
  142. * callbacks.
  143. * @return {function(...params: *): Observable} A function which returns the
  144. * Observable that delivers the same values the Node.js callback would
  145. * deliver.
  146. * @name bindNodeCallback
  147. */
  148. export function bindNodeCallback<T>(
  149. callbackFunc: Function,
  150. resultSelector: Function|SchedulerLike,
  151. scheduler?: SchedulerLike
  152. ): (...args: any[]) => Observable<T> {
  153. if (resultSelector) {
  154. if (isScheduler(resultSelector)) {
  155. scheduler = resultSelector;
  156. } else {
  157. // DEPRECATED PATH
  158. return (...args: any[]) => bindNodeCallback(callbackFunc, scheduler)(...args).pipe(
  159. map(args => isArray(args) ? resultSelector(...args) : resultSelector(args))
  160. );
  161. }
  162. }
  163. return function(this: any, ...args: any[]): Observable<T> {
  164. const params: ParamsState<T> = {
  165. subject: undefined,
  166. args,
  167. callbackFunc,
  168. scheduler,
  169. context: this,
  170. };
  171. return new Observable<T>(subscriber => {
  172. const { context } = params;
  173. let { subject } = params;
  174. if (!scheduler) {
  175. if (!subject) {
  176. subject = params.subject = new AsyncSubject<T>();
  177. const handler = (...innerArgs: any[]) => {
  178. const err = innerArgs.shift();
  179. if (err) {
  180. subject.error(err);
  181. return;
  182. }
  183. subject.next(innerArgs.length <= 1 ? innerArgs[0] : innerArgs);
  184. subject.complete();
  185. };
  186. try {
  187. callbackFunc.apply(context, [...args, handler]);
  188. } catch (err) {
  189. if (canReportError(subject)) {
  190. subject.error(err);
  191. } else {
  192. console.warn(err);
  193. }
  194. }
  195. }
  196. return subject.subscribe(subscriber);
  197. } else {
  198. return scheduler.schedule<DispatchState<T>>(dispatch, 0, { params, subscriber, context });
  199. }
  200. });
  201. };
  202. }
  203. interface DispatchState<T> {
  204. subscriber: Subscriber<T>;
  205. context: any;
  206. params: ParamsState<T>;
  207. }
  208. interface ParamsState<T> {
  209. callbackFunc: Function;
  210. args: any[];
  211. scheduler: SchedulerLike;
  212. subject: AsyncSubject<T>;
  213. context: any;
  214. }
  215. function dispatch<T>(this: SchedulerAction<DispatchState<T>>, state: DispatchState<T>) {
  216. const { params, subscriber, context } = state;
  217. const { callbackFunc, args, scheduler } = params;
  218. let subject = params.subject;
  219. if (!subject) {
  220. subject = params.subject = new AsyncSubject<T>();
  221. const handler = (...innerArgs: any[]) => {
  222. const err = innerArgs.shift();
  223. if (err) {
  224. this.add(scheduler.schedule<DispatchErrorArg<T>>(dispatchError, 0, { err, subject }));
  225. } else {
  226. const value = innerArgs.length <= 1 ? innerArgs[0] : innerArgs;
  227. this.add(scheduler.schedule<DispatchNextArg<T>>(dispatchNext, 0, { value, subject }));
  228. }
  229. };
  230. try {
  231. callbackFunc.apply(context, [...args, handler]);
  232. } catch (err) {
  233. this.add(scheduler.schedule<DispatchErrorArg<T>>(dispatchError, 0, { err, subject }));
  234. }
  235. }
  236. this.add(subject.subscribe(subscriber));
  237. }
  238. interface DispatchNextArg<T> {
  239. subject: AsyncSubject<T>;
  240. value: T;
  241. }
  242. function dispatchNext<T>(arg: DispatchNextArg<T>) {
  243. const { value, subject } = arg;
  244. subject.next(value);
  245. subject.complete();
  246. }
  247. interface DispatchErrorArg<T> {
  248. subject: AsyncSubject<T>;
  249. err: any;
  250. }
  251. function dispatchError<T>(arg: DispatchErrorArg<T>) {
  252. const { err, subject } = arg;
  253. subject.error(err);
  254. }