053ce7678167f91481e0cb6d3b2b4bef8a2b1d124e23c8f321fa010efd7925ae030be0b31fc34923d467e698fd1a8c14ef568e131ba06670b2f7f6a1a53d8f 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. import { PartialObserver, ObservableNotification, CompleteNotification, NextNotification, ErrorNotification } from './types';
  2. import { Observable } from './Observable';
  3. import { EMPTY } from './observable/empty';
  4. import { of } from './observable/of';
  5. import { throwError } from './observable/throwError';
  6. import { isFunction } from './util/isFunction';
  7. // TODO: When this enum is removed, replace it with a type alias. See #4556.
  8. /**
  9. * @deprecated Use a string literal instead. `NotificationKind` will be replaced with a type alias in v8.
  10. * It will not be replaced with a const enum as those are not compatible with isolated modules.
  11. */
  12. export enum NotificationKind {
  13. NEXT = 'N',
  14. ERROR = 'E',
  15. COMPLETE = 'C',
  16. }
  17. /**
  18. * Represents a push-based event or value that an {@link Observable} can emit.
  19. * This class is particularly useful for operators that manage notifications,
  20. * like {@link materialize}, {@link dematerialize}, {@link observeOn}, and
  21. * others. Besides wrapping the actual delivered value, it also annotates it
  22. * with metadata of, for instance, what type of push message it is (`next`,
  23. * `error`, or `complete`).
  24. *
  25. * @see {@link materialize}
  26. * @see {@link dematerialize}
  27. * @see {@link observeOn}
  28. * @deprecated It is NOT recommended to create instances of `Notification` directly.
  29. * Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.
  30. * For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.
  31. * Will be removed in v8.
  32. */
  33. export class Notification<T> {
  34. /**
  35. * A value signifying that the notification will "next" if observed. In truth,
  36. * This is really synonymous with just checking `kind === "N"`.
  37. * @deprecated Will be removed in v8. Instead, just check to see if the value of `kind` is `"N"`.
  38. */
  39. readonly hasValue: boolean;
  40. /**
  41. * Creates a "Next" notification object.
  42. * @param kind Always `'N'`
  43. * @param value The value to notify with if observed.
  44. * @deprecated Internal implementation detail. Use {@link Notification#createNext createNext} instead.
  45. */
  46. constructor(kind: 'N', value?: T);
  47. /**
  48. * Creates an "Error" notification object.
  49. * @param kind Always `'E'`
  50. * @param value Always `undefined`
  51. * @param error The error to notify with if observed.
  52. * @deprecated Internal implementation detail. Use {@link Notification#createError createError} instead.
  53. */
  54. constructor(kind: 'E', value: undefined, error: any);
  55. /**
  56. * Creates a "completion" notification object.
  57. * @param kind Always `'C'`
  58. * @deprecated Internal implementation detail. Use {@link Notification#createComplete createComplete} instead.
  59. */
  60. constructor(kind: 'C');
  61. constructor(public readonly kind: 'N' | 'E' | 'C', public readonly value?: T, public readonly error?: any) {
  62. this.hasValue = kind === 'N';
  63. }
  64. /**
  65. * Executes the appropriate handler on a passed `observer` given the `kind` of notification.
  66. * If the handler is missing it will do nothing. Even if the notification is an error, if
  67. * there is no error handler on the observer, an error will not be thrown, it will noop.
  68. * @param observer The observer to notify.
  69. */
  70. observe(observer: PartialObserver<T>): void {
  71. return observeNotification(this as ObservableNotification<T>, observer);
  72. }
  73. /**
  74. * Executes a notification on the appropriate handler from a list provided.
  75. * If a handler is missing for the kind of notification, nothing is called
  76. * and no error is thrown, it will be a noop.
  77. * @param next A next handler
  78. * @param error An error handler
  79. * @param complete A complete handler
  80. * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
  81. */
  82. do(next: (value: T) => void, error: (err: any) => void, complete: () => void): void;
  83. /**
  84. * Executes a notification on the appropriate handler from a list provided.
  85. * If a handler is missing for the kind of notification, nothing is called
  86. * and no error is thrown, it will be a noop.
  87. * @param next A next handler
  88. * @param error An error handler
  89. * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
  90. */
  91. do(next: (value: T) => void, error: (err: any) => void): void;
  92. /**
  93. * Executes the next handler if the Notification is of `kind` `"N"`. Otherwise
  94. * this will not error, and it will be a noop.
  95. * @param next The next handler
  96. * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
  97. */
  98. do(next: (value: T) => void): void;
  99. do(nextHandler: (value: T) => void, errorHandler?: (err: any) => void, completeHandler?: () => void): void {
  100. const { kind, value, error } = this;
  101. return kind === 'N' ? nextHandler?.(value!) : kind === 'E' ? errorHandler?.(error) : completeHandler?.();
  102. }
  103. /**
  104. * Executes a notification on the appropriate handler from a list provided.
  105. * If a handler is missing for the kind of notification, nothing is called
  106. * and no error is thrown, it will be a noop.
  107. * @param next A next handler
  108. * @param error An error handler
  109. * @param complete A complete handler
  110. * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
  111. */
  112. accept(next: (value: T) => void, error: (err: any) => void, complete: () => void): void;
  113. /**
  114. * Executes a notification on the appropriate handler from a list provided.
  115. * If a handler is missing for the kind of notification, nothing is called
  116. * and no error is thrown, it will be a noop.
  117. * @param next A next handler
  118. * @param error An error handler
  119. * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
  120. */
  121. accept(next: (value: T) => void, error: (err: any) => void): void;
  122. /**
  123. * Executes the next handler if the Notification is of `kind` `"N"`. Otherwise
  124. * this will not error, and it will be a noop.
  125. * @param next The next handler
  126. * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
  127. */
  128. accept(next: (value: T) => void): void;
  129. /**
  130. * Executes the appropriate handler on a passed `observer` given the `kind` of notification.
  131. * If the handler is missing it will do nothing. Even if the notification is an error, if
  132. * there is no error handler on the observer, an error will not be thrown, it will noop.
  133. * @param observer The observer to notify.
  134. * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.
  135. */
  136. accept(observer: PartialObserver<T>): void;
  137. accept(nextOrObserver: PartialObserver<T> | ((value: T) => void), error?: (err: any) => void, complete?: () => void) {
  138. return isFunction((nextOrObserver as any)?.next)
  139. ? this.observe(nextOrObserver as PartialObserver<T>)
  140. : this.do(nextOrObserver as (value: T) => void, error as any, complete as any);
  141. }
  142. /**
  143. * Returns a simple Observable that just delivers the notification represented
  144. * by this Notification instance.
  145. *
  146. * @deprecated Will be removed in v8. To convert a `Notification` to an {@link Observable},
  147. * use {@link of} and {@link dematerialize}: `of(notification).pipe(dematerialize())`.
  148. */
  149. toObservable(): Observable<T> {
  150. const { kind, value, error } = this;
  151. // Select the observable to return by `kind`
  152. const result =
  153. kind === 'N'
  154. ? // Next kind. Return an observable of that value.
  155. of(value!)
  156. : //
  157. kind === 'E'
  158. ? // Error kind. Return an observable that emits the error.
  159. throwError(() => error)
  160. : //
  161. kind === 'C'
  162. ? // Completion kind. Kind is "C", return an observable that just completes.
  163. EMPTY
  164. : // Unknown kind, return falsy, so we error below.
  165. 0;
  166. if (!result) {
  167. // TODO: consider removing this check. The only way to cause this would be to
  168. // use the Notification constructor directly in a way that is not type-safe.
  169. // and direct use of the Notification constructor is deprecated.
  170. throw new TypeError(`Unexpected notification kind ${kind}`);
  171. }
  172. return result;
  173. }
  174. private static completeNotification = new Notification('C') as Notification<never> & CompleteNotification;
  175. /**
  176. * A shortcut to create a Notification instance of the type `next` from a
  177. * given value.
  178. * @param value The `next` value.
  179. * @return The "next" Notification representing the argument.
  180. * @deprecated It is NOT recommended to create instances of `Notification` directly.
  181. * Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.
  182. * For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.
  183. * Will be removed in v8.
  184. */
  185. static createNext<T>(value: T) {
  186. return new Notification('N', value) as Notification<T> & NextNotification<T>;
  187. }
  188. /**
  189. * A shortcut to create a Notification instance of the type `error` from a
  190. * given error.
  191. * @param err The `error` error.
  192. * @return The "error" Notification representing the argument.
  193. * @deprecated It is NOT recommended to create instances of `Notification` directly.
  194. * Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.
  195. * For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.
  196. * Will be removed in v8.
  197. */
  198. static createError(err?: any) {
  199. return new Notification('E', undefined, err) as Notification<never> & ErrorNotification;
  200. }
  201. /**
  202. * A shortcut to create a Notification instance of the type `complete`.
  203. * @return The valueless "complete" Notification.
  204. * @deprecated It is NOT recommended to create instances of `Notification` directly.
  205. * Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.
  206. * For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.
  207. * Will be removed in v8.
  208. */
  209. static createComplete(): Notification<never> & CompleteNotification {
  210. return Notification.completeNotification;
  211. }
  212. }
  213. /**
  214. * Executes the appropriate handler on a passed `observer` given the `kind` of notification.
  215. * If the handler is missing it will do nothing. Even if the notification is an error, if
  216. * there is no error handler on the observer, an error will not be thrown, it will noop.
  217. * @param notification The notification object to observe.
  218. * @param observer The observer to notify.
  219. */
  220. export function observeNotification<T>(notification: ObservableNotification<T>, observer: PartialObserver<T>) {
  221. const { kind, value, error } = notification as any;
  222. if (typeof kind !== 'string') {
  223. throw new TypeError('Invalid notification, missing "kind"');
  224. }
  225. kind === 'N' ? observer.next?.(value!) : kind === 'E' ? observer.error?.(error) : observer.complete?.();
  226. }