routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+109
@@ -0,0 +1,109 @@
|
||||
import { OperatorFunction, ObservableInput, ObservedValueOf, SubjectLike } from '../types';
|
||||
import { Observable } from '../Observable';
|
||||
import { Subject } from '../Subject';
|
||||
import { innerFrom } from '../observable/innerFrom';
|
||||
import { operate } from '../util/lift';
|
||||
import { fromSubscribable } from '../observable/fromSubscribable';
|
||||
|
||||
/**
|
||||
* An object used to configure {@link connect} operator.
|
||||
*/
|
||||
export interface ConnectConfig<T> {
|
||||
/**
|
||||
* A factory function used to create the Subject through which the source
|
||||
* is multicast. By default, this creates a {@link Subject}.
|
||||
*/
|
||||
connector: () => SubjectLike<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default configuration for `connect`.
|
||||
*/
|
||||
const DEFAULT_CONFIG: ConnectConfig<unknown> = {
|
||||
connector: () => new Subject<unknown>(),
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an observable by multicasting the source within a function that
|
||||
* allows the developer to define the usage of the multicast prior to connection.
|
||||
*
|
||||
* This is particularly useful if the observable source you wish to multicast could
|
||||
* be synchronous or asynchronous. This sets it apart from {@link share}, which, in the
|
||||
* case of totally synchronous sources will fail to share a single subscription with
|
||||
* multiple consumers, as by the time the subscription to the result of {@link share}
|
||||
* has returned, if the source is synchronous its internal reference count will jump from
|
||||
* 0 to 1 back to 0 and reset.
|
||||
*
|
||||
* To use `connect`, you provide a `selector` function that will give you
|
||||
* a multicast observable that is not yet connected. You then use that multicast observable
|
||||
* to create a resulting observable that, when subscribed, will set up your multicast. This is
|
||||
* generally, but not always, accomplished with {@link merge}.
|
||||
*
|
||||
* Note that using a {@link takeUntil} inside of `connect`'s `selector` _might_ mean you were looking
|
||||
* to use the {@link takeWhile} operator instead.
|
||||
*
|
||||
* When you subscribe to the result of `connect`, the `selector` function will be called. After
|
||||
* the `selector` function returns, the observable it returns will be subscribed to, _then_ the
|
||||
* multicast will be connected to the source.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* Sharing a totally synchronous observable
|
||||
*
|
||||
* ```ts
|
||||
* import { of, tap, connect, merge, map, filter } from 'rxjs';
|
||||
*
|
||||
* const source$ = of(1, 2, 3, 4, 5).pipe(
|
||||
* tap({
|
||||
* subscribe: () => console.log('subscription started'),
|
||||
* next: n => console.log(`source emitted ${ n }`)
|
||||
* })
|
||||
* );
|
||||
*
|
||||
* source$.pipe(
|
||||
* // Notice in here we're merging 3 subscriptions to `shared$`.
|
||||
* connect(shared$ => merge(
|
||||
* shared$.pipe(map(n => `all ${ n }`)),
|
||||
* shared$.pipe(filter(n => n % 2 === 0), map(n => `even ${ n }`)),
|
||||
* shared$.pipe(filter(n => n % 2 === 1), map(n => `odd ${ n }`))
|
||||
* ))
|
||||
* )
|
||||
* .subscribe(console.log);
|
||||
*
|
||||
* // Expected output: (notice only one subscription)
|
||||
* 'subscription started'
|
||||
* 'source emitted 1'
|
||||
* 'all 1'
|
||||
* 'odd 1'
|
||||
* 'source emitted 2'
|
||||
* 'all 2'
|
||||
* 'even 2'
|
||||
* 'source emitted 3'
|
||||
* 'all 3'
|
||||
* 'odd 3'
|
||||
* 'source emitted 4'
|
||||
* 'all 4'
|
||||
* 'even 4'
|
||||
* 'source emitted 5'
|
||||
* 'all 5'
|
||||
* 'odd 5'
|
||||
* ```
|
||||
*
|
||||
* @param selector A function used to set up the multicast. Gives you a multicast observable
|
||||
* that is not yet connected. With that, you're expected to create and return
|
||||
* and Observable, that when subscribed to, will utilize the multicast observable.
|
||||
* After this function is executed -- and its return value subscribed to -- the
|
||||
* operator will subscribe to the source, and the connection will be made.
|
||||
* @param config The configuration object for `connect`.
|
||||
*/
|
||||
export function connect<T, O extends ObservableInput<unknown>>(
|
||||
selector: (shared: Observable<T>) => O,
|
||||
config: ConnectConfig<T> = DEFAULT_CONFIG
|
||||
): OperatorFunction<T, ObservedValueOf<O>> {
|
||||
const { connector } = config;
|
||||
return operate((source, subscriber) => {
|
||||
const subject = connector();
|
||||
innerFrom(selector(fromSubscribable(subject))).subscribe(subscriber);
|
||||
subscriber.add(source.subscribe(subject));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user