Skip to content

Commit d11f32e

Browse files
kwonojbenlesh
authored andcommitted
feat(operator): add every operator
1 parent 8342430 commit d11f32e

File tree

7 files changed

+214
-0
lines changed

7 files changed

+214
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
var RxOld = require("rx");
2+
var RxNew = require("../../../../index");
3+
4+
module.exports = function (suite) {
5+
6+
var predicate = function(x) {
7+
return x < 50;
8+
}
9+
10+
var testThis = {};
11+
12+
var oldEveryPredicateThisArgs = RxOld.Observable.range(0, 25, RxOld.Scheduler.immediate).every(predicate, testThis);
13+
var newEveryPredicateThisArgs = RxNew.Observable.range(0, 25).every(predicate, testThis);
14+
15+
return suite
16+
.add('old every(predicate, thisArg) with immediate scheduler', function () {
17+
oldEveryPredicateThisArgs.subscribe(_next, _error, _complete);
18+
})
19+
.add('new every(predicate, thisArg) with immediate scheduler', function () {
20+
newEveryPredicateThisArgs.subscribe(_next, _error, _complete);
21+
});
22+
23+
function _next(x) { }
24+
function _error(e){ }
25+
function _complete(){ }
26+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
var RxOld = require("rx");
2+
var RxNew = require("../../../../index");
3+
4+
module.exports = function (suite) {
5+
6+
var predicate = function(x) {
7+
return x < 50;
8+
}
9+
10+
var oldEveryPredicateArgs = RxOld.Observable.range(0, 25, RxOld.Scheduler.immediate).every(predicate);
11+
var newEveryPredicateArgs = RxNew.Observable.range(0, 25).every(predicate);
12+
13+
return suite
14+
.add('old every(predicate) with immediate scheduler', function () {
15+
oldEveryPredicateArgs.subscribe(_next, _error, _complete);
16+
})
17+
.add('new every(predicate) with immediate scheduler', function () {
18+
newEveryPredicateArgs.subscribe(_next, _error, _complete);
19+
});
20+
21+
function _next(x) { }
22+
function _error(e){ }
23+
function _complete(){ }
24+
};

spec/operators/every-spec.js

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* globals describe, it, expect, expectObservable, hot */
2+
var Rx = require('../../dist/cjs/Rx');
3+
4+
describe('Observable.prototype.every()', function() {
5+
function truePredicate(x) {
6+
return true;
7+
}
8+
9+
function predicate(x) {
10+
return x % 5 === 0;
11+
}
12+
13+
it('should emit true if source is empty', function() {
14+
var source = hot('-----|');
15+
var expected = '-----(x|)';
16+
17+
expectObservable(source.every(predicate)).toBe(expected, {x: true});
18+
});
19+
20+
it('should emit false if single source of element does not match with predicate', function() {
21+
var source = hot('--a--|');
22+
var expected = '--(x|)';
23+
24+
expectObservable(source.every(predicate)).toBe(expected, {x: false});
25+
});
26+
27+
it('should emit false if none of element does not match with predicate', function() {
28+
var source = hot('--a--b--c--d--e--|');
29+
var expected = '--(x|)';
30+
31+
expectObservable(source.every(predicate)).toBe(expected, {x: false});
32+
});
33+
34+
it('should return false if only some of element matches with predicate', function() {
35+
var source = hot('--a--b--c--d--e--|', {a: 5, b: 10, c: 15});
36+
var expected = '-----------(x|)';
37+
38+
expectObservable(source.every(predicate)).toBe(expected, {x: false});
39+
});
40+
41+
it('should emit true if single source element match with predicate', function() {
42+
var source = hot('--a--|', {a: 5});
43+
var expected = '-----(x|)';
44+
45+
expectObservable(source.every(predicate)).toBe(expected, {x: true});
46+
});
47+
48+
it('should emit true if all source element matches with predicate', function() {
49+
var source = hot('--a--b--c--d--e--|', {a: 5, b: 10, c: 15, d: 20, e: 25});
50+
var expected = '-----------------(x|)';
51+
52+
expectObservable(source.every(predicate)).toBe(expected, {x: true});
53+
});
54+
55+
it('should raise error if source raises error', function() {
56+
var source = hot('--#');
57+
var expected = '--#';
58+
59+
expectObservable(source.every(truePredicate)).toBe(expected);
60+
});
61+
62+
it('should not completes if source never emits', function() {
63+
var expected = '-';
64+
65+
expectObservable(Rx.Observable.never().every(truePredicate)).toBe(expected);
66+
});
67+
68+
it('should emit true if source element matches with predicate after subscription', function() {
69+
var source = hot('--z--^--a--b--c--d--e--|', {a: 5, b: 10, c: 15, d: 20, e: 25});
70+
var expected = '------------------(x|)';
71+
72+
expectObservable(source.every(predicate)).toBe(expected, {x: true});
73+
});
74+
75+
it('should emit false if source element does not match with predicate after subscription', function() {
76+
var source = hot('--z--^--b--c--z--d--|', {a: 5, b: 10, c: 15, d: 20});
77+
var expected = '---------(x|)';
78+
79+
expectObservable(source.every(predicate)).toBe(expected, {x: false});
80+
});
81+
82+
it('should raise error if source raises error after subscription', function() {
83+
var source = hot('--z--^--#');
84+
var expected = '---#';
85+
86+
expectObservable(source.every(truePredicate)).toBe(expected);
87+
});
88+
89+
it('should emit true if source does not emit after subscription', function() {
90+
var source = hot('--z--^-----|');
91+
var expected = '------(x|)';
92+
93+
expectObservable(source.every(predicate)).toBe(expected, {x: true});
94+
});
95+
96+
});

src/CoreOperators.ts

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export interface CoreOperators<T> {
3333
ignoreElements?: () => Observable<T>;
3434
isEmpty?: () => Observable<boolean>;
3535
last?: <R>(predicate?: (value: T, index:number) => boolean, resultSelector?: (value: T, index: number) => R, thisArg?: any, defaultValue?: any) => Observable<T>;
36+
every?: (predicate: (value: T, index:number) => boolean, thisArg?: any) => Observable<T>;
3637
map?: <T, R>(project: (x: T, ix?: number) => R, thisArg?: any) => Observable<R>;
3738
mapTo?: <R>(value: R) => Observable<R>;
3839
materialize?: () => Observable<any>;

src/Rx.KitchenSink.ts

+3
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ observableProto.ignoreElements = ignoreElements;
155155
import isEmpty from './operators/isEmpty';
156156
observableProto.isEmpty = isEmpty;
157157

158+
import every from './operators/every';
159+
observableProto.every = every;
160+
158161
import last from './operators/last';
159162
observableProto.last = last;
160163

src/Rx.ts

+3
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ observableProto.ignoreElements = ignoreElements;
135135
import isEmpty from './operators/isEmpty';
136136
observableProto.isEmpty = isEmpty;
137137

138+
import every from './operators/every';
139+
observableProto.every = every;
140+
138141
import last from './operators/last';
139142
observableProto.last = last;
140143

src/operators/every.ts

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import Operator from '../Operator';
2+
import Observer from '../Observer';
3+
import Observable from '../Observable';
4+
import Subscriber from '../Subscriber';
5+
6+
import tryCatch from '../util/tryCatch';
7+
import {errorObject} from '../util/errorObject';
8+
import bindCallback from '../util/bindCallback';
9+
10+
export default function every<T>(predicate: (value: T, index: number, source: Observable<T>) => boolean, thisArg?: any): Observable<T>{
11+
return this.lift(new EveryOperator(predicate, thisArg, this));
12+
}
13+
14+
class EveryOperator<T, R> implements Operator<T, R> {
15+
constructor(private predicate: (value: T, index: number, source: Observable<T>) => boolean,
16+
private thisArg?: any, private source?: Observable<T>) {
17+
18+
}
19+
20+
call(observer: Subscriber<R>): Subscriber<T> {
21+
return new EverySubscriber(observer, this.predicate, this.thisArg, this.source);
22+
}
23+
}
24+
25+
class EverySubscriber<T> extends Subscriber<T> {
26+
private predicate: Function = undefined;
27+
private index: number = 0;
28+
29+
constructor(destination: Observer<T>, predicate?: (value: T, index: number, source: Observable<T>) => boolean,
30+
private thisArg?: any, private source?: Observable<T>) {
31+
super(destination);
32+
33+
if(typeof predicate === 'function') {
34+
this.predicate = bindCallback(predicate, thisArg, 3);
35+
}
36+
}
37+
38+
private notifyComplete(everyValueMatch: boolean): void {
39+
this.destination.next(everyValueMatch);
40+
this.destination.complete();
41+
}
42+
43+
_next(value: T) {
44+
const predicate = this.predicate;
45+
46+
if (predicate === undefined) {
47+
this.destination.error(new TypeError('predicate must be a function'));
48+
}
49+
50+
let result = tryCatch(predicate)(value, this.index++, this.source);
51+
if (result === errorObject) {
52+
this.destination.error(result.e);
53+
} else if (!result) {
54+
this.notifyComplete(false);
55+
}
56+
}
57+
58+
_complete() {
59+
this.notifyComplete(true);
60+
}
61+
}

0 commit comments

Comments
 (0)