Buckets:
| import { MonoTypeOperatorFunction } from '../types'; | |
| import { identity } from '../util/identity'; | |
| import { operate } from '../util/lift'; | |
| import { createOperatorSubscriber } from './OperatorSubscriber'; | |
| export function distinctUntilChanged<T>(comparator?: (previous: T, current: T) => boolean): MonoTypeOperatorFunction<T>; | |
| export function distinctUntilChanged<T, K>( | |
| comparator: (previous: K, current: K) => boolean, | |
| keySelector: (value: T) => K | |
| ): MonoTypeOperatorFunction<T>; | |
| /** | |
| * Returns a result {@link Observable} that emits all values pushed by the source observable if they | |
| * are distinct in comparison to the last value the result observable emitted. | |
| * | |
| * When provided without parameters or with the first parameter (`{@link distinctUntilChanged#comparator comparator}`), | |
| * it behaves like this: | |
| * | |
| * 1. It will always emit the first value from the source. | |
| * 2. For all subsequent values pushed by the source, they will be compared to the previously emitted values | |
| * using the provided `comparator` or an `===` equality check. | |
| * 3. If the value pushed by the source is determined to be unequal by this check, that value is emitted and | |
| * becomes the new "previously emitted value" internally. | |
| * | |
| * When the second parameter (`{@link distinctUntilChanged#keySelector keySelector}`) is provided, the behavior | |
| * changes: | |
| * | |
| * 1. It will always emit the first value from the source. | |
| * 2. The `keySelector` will be run against all values, including the first value. | |
| * 3. For all values after the first, the selected key will be compared against the key selected from | |
| * the previously emitted value using the `comparator`. | |
| * 4. If the keys are determined to be unequal by this check, the value (not the key), is emitted | |
| * and the selected key from that value is saved for future comparisons against other keys. | |
| * | |
| * ## Examples | |
| * | |
| * A very basic example with no `{@link distinctUntilChanged#comparator comparator}`. Note that `1` is emitted more than once, | |
| * because it's distinct in comparison to the _previously emitted_ value, | |
| * not in comparison to _all other emitted values_. | |
| * | |
| * ```ts | |
| * import { of, distinctUntilChanged } from 'rxjs'; | |
| * | |
| * of(1, 1, 1, 2, 2, 2, 1, 1, 3, 3) | |
| * .pipe(distinctUntilChanged()) | |
| * .subscribe(console.log); | |
| * // Logs: 1, 2, 1, 3 | |
| * ``` | |
| * | |
| * With a `{@link distinctUntilChanged#comparator comparator}`, you can do custom comparisons. Let's say | |
| * you only want to emit a value when all of its components have | |
| * changed: | |
| * | |
| * ```ts | |
| * import { of, distinctUntilChanged } from 'rxjs'; | |
| * | |
| * const totallyDifferentBuilds$ = of( | |
| * { engineVersion: '1.1.0', transmissionVersion: '1.2.0' }, | |
| * { engineVersion: '1.1.0', transmissionVersion: '1.4.0' }, | |
| * { engineVersion: '1.3.0', transmissionVersion: '1.4.0' }, | |
| * { engineVersion: '1.3.0', transmissionVersion: '1.5.0' }, | |
| * { engineVersion: '2.0.0', transmissionVersion: '1.5.0' } | |
| * ).pipe( | |
| * distinctUntilChanged((prev, curr) => { | |
| * return ( | |
| * prev.engineVersion === curr.engineVersion || | |
| * prev.transmissionVersion === curr.transmissionVersion | |
| * ); | |
| * }) | |
| * ); | |
| * | |
| * totallyDifferentBuilds$.subscribe(console.log); | |
| * | |
| * // Logs: | |
| * // { engineVersion: '1.1.0', transmissionVersion: '1.2.0' } | |
| * // { engineVersion: '1.3.0', transmissionVersion: '1.4.0' } | |
| * // { engineVersion: '2.0.0', transmissionVersion: '1.5.0' } | |
| * ``` | |
| * | |
| * You can also provide a custom `{@link distinctUntilChanged#comparator comparator}` to check that emitted | |
| * changes are only in one direction. Let's say you only want to get | |
| * the next record temperature: | |
| * | |
| * ```ts | |
| * import { of, distinctUntilChanged } from 'rxjs'; | |
| * | |
| * const temps$ = of(30, 31, 20, 34, 33, 29, 35, 20); | |
| * | |
| * const recordHighs$ = temps$.pipe( | |
| * distinctUntilChanged((prevHigh, temp) => { | |
| * // If the current temp is less than | |
| * // or the same as the previous record, | |
| * // the record hasn't changed. | |
| * return temp <= prevHigh; | |
| * }) | |
| * ); | |
| * | |
| * recordHighs$.subscribe(console.log); | |
| * // Logs: 30, 31, 34, 35 | |
| * ``` | |
| * | |
| * Selecting update events only when the `updatedBy` field shows | |
| * the account changed hands. | |
| * | |
| * ```ts | |
| * import { of, distinctUntilChanged } from 'rxjs'; | |
| * | |
| * // A stream of updates to a given account | |
| * const accountUpdates$ = of( | |
| * { updatedBy: 'blesh', data: [] }, | |
| * { updatedBy: 'blesh', data: [] }, | |
| * { updatedBy: 'ncjamieson', data: [] }, | |
| * { updatedBy: 'ncjamieson', data: [] }, | |
| * { updatedBy: 'blesh', data: [] } | |
| * ); | |
| * | |
| * // We only want the events where it changed hands | |
| * const changedHands$ = accountUpdates$.pipe( | |
| * distinctUntilChanged(undefined, update => update.updatedBy) | |
| * ); | |
| * | |
| * changedHands$.subscribe(console.log); | |
| * // Logs: | |
| * // { updatedBy: 'blesh', data: Array[0] } | |
| * // { updatedBy: 'ncjamieson', data: Array[0] } | |
| * // { updatedBy: 'blesh', data: Array[0] } | |
| * ``` | |
| * | |
| * @see {@link distinct} | |
| * @see {@link distinctUntilKeyChanged} | |
| * | |
| * @param comparator A function used to compare the previous and current keys for | |
| * equality. Defaults to a `===` check. | |
| * @param keySelector Used to select a key value to be passed to the `comparator`. | |
| * | |
| * @return A function that returns an Observable that emits items from the | |
| * source Observable with distinct values. | |
| */ | |
| export function distinctUntilChanged<T, K>( | |
| comparator?: (previous: K, current: K) => boolean, | |
| keySelector: (value: T) => K = identity as (value: T) => K | |
| ): MonoTypeOperatorFunction<T> { | |
| // We've been allowing `null` do be passed as the `compare`, so we can't do | |
| // a default value for the parameter, because that will only work | |
| // for `undefined`. | |
| comparator = comparator ?? defaultCompare; | |
| return operate((source, subscriber) => { | |
| // The previous key, used to compare against keys selected | |
| // from new arrivals to determine "distinctiveness". | |
| let previousKey: K; | |
| // Whether or not this is the first value we've gotten. | |
| let first = true; | |
| source.subscribe( | |
| createOperatorSubscriber(subscriber, (value) => { | |
| // We always call the key selector. | |
| const currentKey = keySelector(value); | |
| // If it's the first value, we always emit it. | |
| // Otherwise, we compare this key to the previous key, and | |
| // if the comparer returns false, we emit. | |
| if (first || !comparator!(previousKey, currentKey)) { | |
| // Update our state *before* we emit the value | |
| // as emission can be the source of re-entrant code | |
| // in functional libraries like this. We only really | |
| // need to do this if it's the first value, or if the | |
| // key we're tracking in previous needs to change. | |
| first = false; | |
| previousKey = currentKey; | |
| // Emit the value! | |
| subscriber.next(value); | |
| } | |
| }) | |
| ); | |
| }); | |
| } | |
| function defaultCompare(a: any, b: any) { | |
| return a === b; | |
| } | |
Xet Storage Details
- Size:
- 6.91 kB
- Xet hash:
- fd2248cbcde4300d677169cdc67930a91d4d212c193426f7fe348ccaa99d8184
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.