-
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(filter): add higher-order lettable version of filter
- Loading branch information
Showing
3 changed files
with
105 additions
and
46 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { Operator } from '../Operator'; | ||
import { Subscriber } from '../Subscriber'; | ||
import { Observable } from '../Observable'; | ||
import { TeardownLogic } from '../Subscription'; | ||
import { OperatorFunction } from './OperatorFunction'; | ||
|
||
/* tslint:disable:max-line-length */ | ||
export function filter<T, S extends T>(predicate: (value: T, index: number) => value is S, | ||
thisArg?: any): OperatorFunction<T, S>; | ||
export function filter<T>(predicate: (value: T, index: number) => boolean, | ||
thisArg?: any): OperatorFunction<T, T>; | ||
/* tslint:enable:max-line-length */ | ||
|
||
/** | ||
* Filter items emitted by the source Observable by only emitting those that | ||
* satisfy a specified predicate. | ||
* | ||
* <span class="informal">Like | ||
* [Array.prototype.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), | ||
* it only emits a value from the source if it passes a criterion function.</span> | ||
* | ||
* <img src="./img/filter.png" width="100%"> | ||
* | ||
* Similar to the well-known `Array.prototype.filter` method, this operator | ||
* takes values from the source Observable, passes them through a `predicate` | ||
* function and only emits those values that yielded `true`. | ||
* | ||
* @example <caption>Emit only click events whose target was a DIV element</caption> | ||
* var clicks = Rx.Observable.fromEvent(document, 'click'); | ||
* var clicksOnDivs = clicks.filter(ev => ev.target.tagName === 'DIV'); | ||
* clicksOnDivs.subscribe(x => console.log(x)); | ||
* | ||
* @see {@link distinct} | ||
* @see {@link distinctUntilChanged} | ||
* @see {@link distinctUntilKeyChanged} | ||
* @see {@link ignoreElements} | ||
* @see {@link partition} | ||
* @see {@link skip} | ||
* | ||
* @param {function(value: T, index: number): boolean} predicate A function that | ||
* evaluates each value emitted by the source Observable. If it returns `true`, | ||
* the value is emitted, if `false` the value is not passed to the output | ||
* Observable. The `index` parameter is the number `i` for the i-th source | ||
* emission that has happened since the subscription, starting from the number | ||
* `0`. | ||
* @param {any} [thisArg] An optional argument to determine the value of `this` | ||
* in the `predicate` function. | ||
* @return {Observable} An Observable of values from the source that were | ||
* allowed by the `predicate` function. | ||
* @method filter | ||
* @owner Observable | ||
*/ | ||
export function filter<T>(predicate: (value: T, index: number) => boolean, | ||
thisArg?: any): OperatorFunction<T, T> { | ||
return function filterOperatorFunction(source: Observable<T>): Observable<T> { | ||
return source.lift(new FilterOperator(predicate, thisArg)); | ||
}; | ||
} | ||
|
||
class FilterOperator<T> implements Operator<T, T> { | ||
constructor(private predicate: (value: T, index: number) => boolean, | ||
private thisArg?: any) { | ||
} | ||
|
||
call(subscriber: Subscriber<T>, source: any): TeardownLogic { | ||
return source.subscribe(new FilterSubscriber(subscriber, this.predicate, this.thisArg)); | ||
} | ||
} | ||
|
||
/** | ||
* We need this JSDoc comment for affecting ESDoc. | ||
* @ignore | ||
* @extends {Ignored} | ||
*/ | ||
class FilterSubscriber<T> extends Subscriber<T> { | ||
|
||
count: number = 0; | ||
|
||
constructor(destination: Subscriber<T>, | ||
private predicate: (value: T, index: number) => boolean, | ||
private thisArg: any) { | ||
super(destination); | ||
this.predicate = predicate; | ||
} | ||
|
||
// the try catch block below is left specifically for | ||
// optimization and perf reasons. a tryCatcher is not necessary here. | ||
protected _next(value: T) { | ||
let result: any; | ||
try { | ||
result = this.predicate.call(this.thisArg, value, this.count++); | ||
} catch (err) { | ||
this.destination.error(err); | ||
return; | ||
} | ||
if (result) { | ||
this.destination.next(value); | ||
} | ||
} | ||
} |
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 |
---|---|---|
@@ -1,3 +1,5 @@ | ||
export { OperatorFunction } from './OperatorFunction'; | ||
export { filter } from './filter'; | ||
|
||
export { map } from './map'; | ||
export { mergeMap } from './mergeMap'; |