b6440007500dbcd6e3f706650297168ba4a8fa79512fd7b1aca92e33ad495f70566db2f132eb06aa5787ae3972e75fa56d01f2a23d76eed411b0d2ed645c2a 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { Connectable, ObservableInput, SubjectLike } from '../types';
  2. import { Subject } from '../Subject';
  3. import { Subscription } from '../Subscription';
  4. import { Observable } from '../Observable';
  5. import { defer } from './defer';
  6. export interface ConnectableConfig<T> {
  7. /**
  8. * A factory function used to create the Subject through which the source
  9. * is multicast. By default this creates a {@link Subject}.
  10. */
  11. connector: () => SubjectLike<T>;
  12. /**
  13. * If true, the resulting observable will reset internal state upon disconnection
  14. * and return to a "cold" state. This allows the resulting observable to be
  15. * reconnected.
  16. * If false, upon disconnection, the connecting subject will remain the
  17. * connecting subject, meaning the resulting observable will not go "cold" again,
  18. * and subsequent repeats or resubscriptions will resubscribe to that same subject.
  19. */
  20. resetOnDisconnect?: boolean;
  21. }
  22. /**
  23. * The default configuration for `connectable`.
  24. */
  25. const DEFAULT_CONFIG: ConnectableConfig<unknown> = {
  26. connector: () => new Subject<unknown>(),
  27. resetOnDisconnect: true,
  28. };
  29. /**
  30. * Creates an observable that multicasts once `connect()` is called on it.
  31. *
  32. * @param source The observable source to make connectable.
  33. * @param config The configuration object for `connectable`.
  34. * @returns A "connectable" observable, that has a `connect()` method, that you must call to
  35. * connect the source to all consumers through the subject provided as the connector.
  36. */
  37. export function connectable<T>(source: ObservableInput<T>, config: ConnectableConfig<T> = DEFAULT_CONFIG): Connectable<T> {
  38. // The subscription representing the connection.
  39. let connection: Subscription | null = null;
  40. const { connector, resetOnDisconnect = true } = config;
  41. let subject = connector();
  42. const result: any = new Observable<T>((subscriber) => {
  43. return subject.subscribe(subscriber);
  44. });
  45. // Define the `connect` function. This is what users must call
  46. // in order to "connect" the source to the subject that is
  47. // multicasting it.
  48. result.connect = () => {
  49. if (!connection || connection.closed) {
  50. connection = defer(() => source).subscribe(subject);
  51. if (resetOnDisconnect) {
  52. connection.add(() => (subject = connector()));
  53. }
  54. }
  55. return connection;
  56. };
  57. return result;
  58. }