-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(find): add higher-order lettable version of find
- Loading branch information
Showing
4 changed files
with
110 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { Observable } from '../Observable'; | ||
import { Operator } from '../Operator'; | ||
import { Subscriber } from '../Subscriber'; | ||
import { OperatorFunction, MonoTypeOperatorFunction } from '../interfaces'; | ||
|
||
export function find<T, S extends T>(predicate: (value: T, index: number, source: Observable<T>) => value is S, | ||
thisArg?: any): OperatorFunction<T, S>; | ||
export function find<T, S extends T>(predicate: (value: T, index: number) => value is S, | ||
thisArg?: any): OperatorFunction<T, S>; | ||
export function find<T>(predicate: (value: T, index: number, source: Observable<T>) => boolean, | ||
thisArg?: any): MonoTypeOperatorFunction<T>; | ||
export function find<T>(predicate: (value: T, index: number) => boolean, | ||
thisArg?: any): MonoTypeOperatorFunction<T>; | ||
/** | ||
* Emits only the first value emitted by the source Observable that meets some | ||
* condition. | ||
* | ||
* <span class="informal">Finds the first value that passes some test and emits | ||
* that.</span> | ||
* | ||
* <img src="./img/find.png" width="100%"> | ||
* | ||
* `find` searches for the first item in the source Observable that matches the | ||
* specified condition embodied by the `predicate`, and returns the first | ||
* occurrence in the source. Unlike {@link first}, the `predicate` is required | ||
* in `find`, and does not emit an error if a valid value is not found. | ||
* | ||
* @example <caption>Find and emit the first click that happens on a DIV element</caption> | ||
* var clicks = Rx.Observable.fromEvent(document, 'click'); | ||
* var result = clicks.find(ev => ev.target.tagName === 'DIV'); | ||
* result.subscribe(x => console.log(x)); | ||
* | ||
* @see {@link filter} | ||
* @see {@link first} | ||
* @see {@link findIndex} | ||
* @see {@link take} | ||
* | ||
* @param {function(value: T, index: number, source: Observable<T>): boolean} predicate | ||
* A function called with each item to test for condition matching. | ||
* @param {any} [thisArg] An optional argument to determine the value of `this` | ||
* in the `predicate` function. | ||
* @return {Observable<T>} An Observable of the first item that matches the | ||
* condition. | ||
* @method find | ||
* @owner Observable | ||
*/ | ||
export function find<T>(predicate: (value: T, index: number, source: Observable<T>) => boolean, | ||
thisArg?: any): MonoTypeOperatorFunction<T> { | ||
if (typeof predicate !== 'function') { | ||
throw new TypeError('predicate is not a function'); | ||
} | ||
return (source: Observable<T>) => source.lift(new FindValueOperator(predicate, source, false, thisArg)); | ||
} | ||
|
||
export class FindValueOperator<T> implements Operator<T, T> { | ||
constructor(private predicate: (value: T, index: number, source: Observable<T>) => boolean, | ||
private source: Observable<T>, | ||
private yieldIndex: boolean, | ||
private thisArg?: any) { | ||
} | ||
|
||
call(observer: Subscriber<T>, source: any): any { | ||
return source.subscribe(new FindValueSubscriber(observer, this.predicate, this.source, this.yieldIndex, this.thisArg)); | ||
} | ||
} | ||
|
||
/** | ||
* We need this JSDoc comment for affecting ESDoc. | ||
* @ignore | ||
* @extends {Ignored} | ||
*/ | ||
export class FindValueSubscriber<T> extends Subscriber<T> { | ||
private index: number = 0; | ||
|
||
constructor(destination: Subscriber<T>, | ||
private predicate: (value: T, index: number, source: Observable<T>) => boolean, | ||
private source: Observable<T>, | ||
private yieldIndex: boolean, | ||
private thisArg?: any) { | ||
super(destination); | ||
} | ||
|
||
private notifyComplete(value: any): void { | ||
const destination = this.destination; | ||
|
||
destination.next(value); | ||
destination.complete(); | ||
} | ||
|
||
protected _next(value: T): void { | ||
const { predicate, thisArg } = this; | ||
const index = this.index++; | ||
try { | ||
const result = predicate.call(thisArg || this, value, index, this.source); | ||
if (result) { | ||
this.notifyComplete(this.yieldIndex ? index : value); | ||
} | ||
} catch (err) { | ||
this.destination.error(err); | ||
} | ||
} | ||
|
||
protected _complete(): void { | ||
this.notifyComplete(this.yieldIndex ? -1 : undefined); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters