Skip to content

Commit 17122f9

Browse files
committed
feat(delayWhen): add delayWhen operator
1 parent a55f459 commit 17122f9

File tree

8 files changed

+366
-0
lines changed

8 files changed

+366
-0
lines changed

spec/operators/delayWhen-spec.js

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
/* globals describe, it, expect, expectObservable, expectSubscriptions, hot, cold, rxTestScheduler */
2+
var Rx = require('../../dist/cjs/Rx');
3+
var Observable = Rx.Observable;
4+
5+
describe('Observable.prototype.delayWhen()', function () {
6+
it.asDiagram('delay(durationSelector)')('should delay by duration selector', function () {
7+
var e1 = hot('---a---b---c--|');
8+
var expected = '-----a------c----(b|)';
9+
var subs = '^ !';
10+
var selector = [cold( '--x--|'),
11+
cold( '----------x-|'),
12+
cold( '-x--|')];
13+
var selectorSubs = [' ^ ! ',
14+
' ^ !',
15+
' ^! '];
16+
17+
var idx = 0;
18+
function durationSelector(x) {
19+
return selector[idx++];
20+
}
21+
22+
var result = e1.delayWhen(durationSelector);
23+
24+
expectObservable(result).toBe(expected);
25+
expectSubscriptions(e1.subscriptions).toBe(subs);
26+
expectSubscriptions(selector[0].subscriptions).toBe(selectorSubs[0]);
27+
expectSubscriptions(selector[1].subscriptions).toBe(selectorSubs[1]);
28+
expectSubscriptions(selector[2].subscriptions).toBe(selectorSubs[2]);
29+
});
30+
31+
it('should delay by selector', function () {
32+
var e1 = hot('--a--b--|');
33+
var expected = '---a--b-|';
34+
var subs = '^ !';
35+
var selector = cold( '-x--|');
36+
var selectorSubs = [' ^! ',
37+
' ^! '];
38+
39+
var result = e1.delayWhen(function (x) { return selector; });
40+
41+
expectObservable(result).toBe(expected);
42+
expectSubscriptions(e1.subscriptions).toBe(subs);
43+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
44+
});
45+
46+
it('should raise error if source raises error', function () {
47+
var e1 = hot('--a--#');
48+
var expected = '---a-#';
49+
var subs = '^ !';
50+
var selector = cold( '-x--|');
51+
var selectorSubs = ' ^! ';
52+
53+
var result = e1.delayWhen(function (x) { return selector; });
54+
55+
expectObservable(result).toBe(expected);
56+
expectSubscriptions(e1.subscriptions).toBe(subs);
57+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
58+
});
59+
60+
it('should raise error if selector raises error', function () {
61+
var e1 = hot('--a--b--|');
62+
var expected = '---#';
63+
var subs = '^ !';
64+
var selector = cold( '-#');
65+
var selectorSubs = ' ^! ';
66+
67+
var result = e1.delayWhen(function (x) { return selector; });
68+
69+
expectObservable(result).toBe(expected);
70+
expectSubscriptions(e1.subscriptions).toBe(subs);
71+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
72+
});
73+
74+
it('should delay by selector and completes after value emits', function () {
75+
var e1 = hot('--a--b--|');
76+
var expected = '---------a--(b|)';
77+
var subs = '^ !';
78+
var selector = cold('-------x--|');
79+
var selectorSubs = [' ^ !',
80+
' ^ !'];
81+
82+
var result = e1.delayWhen(function (x) { return selector; });
83+
84+
expectObservable(result).toBe(expected);
85+
expectSubscriptions(e1.subscriptions).toBe(subs);
86+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
87+
});
88+
89+
it('should delay by selector completes if selector does not emits', function () {
90+
var e1 = hot('--a--b--|');
91+
var expected = '------a--(b|)';
92+
var subs = '^ !';
93+
var selector = cold( '----|');
94+
var selectorSubs = [' ^ !',
95+
' ^ !'];
96+
97+
var result = e1.delayWhen(function (x) { return selector; });
98+
99+
expectObservable(result).toBe(expected);
100+
expectSubscriptions(e1.subscriptions).toBe(subs);
101+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
102+
});
103+
104+
it('should not emit if selector never emits', function () {
105+
var e1 = hot('--a--b--|');
106+
var expected = '-';
107+
var subs = '^ ';
108+
var selector = cold( '-');
109+
var selectorSubs = [' ^ ',
110+
' ^ '];
111+
112+
var result = e1.delayWhen(function (x) { return selector; });
113+
114+
expectObservable(result).toBe(expected);
115+
expectSubscriptions(e1.subscriptions).toBe(subs);
116+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
117+
});
118+
119+
it('should delay by first value from selector', function () {
120+
var e1 = hot('--a--b--|');
121+
var expected = '------a--(b|)';
122+
var subs = '^ !';
123+
var selector = cold( '----x--y--|');
124+
var selectorSubs = [' ^ !',
125+
' ^ !'];
126+
127+
var result = e1.delayWhen(function (x) { return selector; });
128+
129+
expectObservable(result).toBe(expected);
130+
expectSubscriptions(e1.subscriptions).toBe(subs);
131+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
132+
});
133+
134+
it('should delay by selector does not completes', function () {
135+
var e1 = hot('--a--b--|');
136+
var expected = '------a--(b|)';
137+
var subs = '^ !';
138+
var selector = cold( '----x-----y---');
139+
var selectorSubs = [' ^ !',
140+
' ^ !'];
141+
142+
var result = e1.delayWhen(function (x) { return selector; });
143+
144+
expectObservable(result).toBe(expected);
145+
expectSubscriptions(e1.subscriptions).toBe(subs);
146+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
147+
});
148+
149+
it('should raise error if selector throws', function () {
150+
var e1 = hot('--a--b--|');
151+
var expected = '--#';
152+
var subs = '^ !';
153+
154+
var err = new Error('error');
155+
var result = e1.delayWhen(function (x) { throw err; });
156+
157+
expectObservable(result).toBe(expected, null, err);
158+
expectSubscriptions(e1.subscriptions).toBe(subs);
159+
});
160+
161+
it('should start subscription when subscription delay emits', function () {
162+
var e1 = hot('-----a---b---|');
163+
var expected = ' -----a---b-|';
164+
var subs = ' ^ !';
165+
var selector = cold( '--x--|');
166+
var selectorSubs = [' ^ !',
167+
' ^ !'];
168+
var subDelay = cold('--x--|');
169+
var subDelaySub = '^ !';
170+
171+
var result = e1.delayWhen(function (x) { return selector; }, subDelay);
172+
173+
expectObservable(result).toBe(expected);
174+
expectSubscriptions(e1.subscriptions).toBe(subs);
175+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
176+
expectSubscriptions(subDelay.subscriptions).toBe(subDelaySub);
177+
});
178+
179+
it('should start subscription when subscription delay completes without emit value', function () {
180+
var e1 = hot('-----a---b---|');
181+
var expected = ' -----a---b-|';
182+
var subs = ' ^ !';
183+
var selector = cold( '--x--|');
184+
var selectorSubs = [' ^ !',
185+
' ^ !'];
186+
var subDelay = cold('--|');
187+
var subDelaySub = '^ !';
188+
189+
var result = e1.delayWhen(function (x) { return selector; }, subDelay);
190+
191+
expectObservable(result).toBe(expected);
192+
expectSubscriptions(e1.subscriptions).toBe(subs);
193+
expectSubscriptions(selector.subscriptions).toBe(selectorSubs);
194+
expectSubscriptions(subDelay.subscriptions).toBe(subDelaySub);
195+
});
196+
197+
it('should raise error when subscription delay raises error', function () {
198+
var e1 = hot('-----a---b---|');
199+
var expected = ' # ';
200+
var selector = cold( '--x--|');
201+
var subDelay = cold('---#');
202+
var subDelaySub = '^ !';
203+
204+
var result = e1.delayWhen(function (x) { return selector; }, subDelay);
205+
206+
expectObservable(result).toBe(expected);
207+
expectSubscriptions(e1.subscriptions).toBe([]);
208+
expectSubscriptions(selector.subscriptions).toBe([]);
209+
expectSubscriptions(subDelay.subscriptions).toBe(subDelaySub);
210+
});
211+
});

src/CoreOperators.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface CoreOperators<T> {
2424
debounceTime?: <R>(dueTime: number, scheduler?: Scheduler) => Observable<R>;
2525
defaultIfEmpty?: <R>(defaultValue?: T | R) => Observable<T> | Observable<R>;
2626
delay?: (delay: number, scheduler?: Scheduler) => Observable<T>;
27+
delayWhen?: (delayDurationSelector: (value: T) => Observable<any>, subscriptionDelay?: Observable<any>) => Observable<T>;
2728
distinctUntilChanged?: (compare?: (x: T, y: T) => boolean) => Observable<T>;
2829
do?: (next?: (x: T) => void, error?: (e: any) => void, complete?: () => void) => Observable<T>;
2930
expand?: <R>(project: (x: T, ix: number) => Observable<R>, concurrent: number, scheduler: Scheduler) => Observable<R>;

src/Observable.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ export class Observable<T> implements CoreOperators<T> {
204204
debounceTime: <R>(dueTime: number, scheduler?: Scheduler) => Observable<R>;
205205
defaultIfEmpty: <R>(defaultValue?: T | R) => Observable<T> | Observable<R>;
206206
delay: (delay: number, scheduler?: Scheduler) => Observable<T>;
207+
delayWhen: (delayDurationSelector: (value: T) => Observable<any>, subscriptionDelay?: Observable<any>) => Observable<T>;
207208
distinctUntilChanged: (compare?: (x: T, y: T) => boolean) => Observable<T>;
208209
do: (next?: (x: T) => void, error?: (e: any) => void, complete?: () => void) => Observable<T>;
209210
expand: <R>(project: (x: T, ix: number) => Observable<R>, concurrent: number, scheduler: Scheduler) => Observable<R>;

src/Rx.DOM.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import './add/operator/debounce';
4949
import './add/operator/debounceTime';
5050
import './add/operator/defaultIfEmpty';
5151
import './add/operator/delay';
52+
import './add/operator/delayWhen';
5253
import './add/operator/distinctUntilChanged';
5354
import './add/operator/do';
5455
import './add/operator/expand';

src/Rx.KitchenSink.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ import './add/operator/debounce';
6565
import './add/operator/debounceTime';
6666
import './add/operator/defaultIfEmpty';
6767
import './add/operator/delay';
68+
import './add/operator/delayWhen';
6869
import './add/operator/distinct';
6970
import './add/operator/distinctKey';
7071
import './add/operator/distinctUntilChanged';

src/Rx.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import './add/operator/debounce';
4848
import './add/operator/debounceTime';
4949
import './add/operator/defaultIfEmpty';
5050
import './add/operator/delay';
51+
import './add/operator/delayWhen';
5152
import './add/operator/distinctUntilChanged';
5253
import './add/operator/do';
5354
import './add/operator/expand';

src/add/operator/delayWhen.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import {Observable} from '../../Observable';
2+
import {delayWhen} from '../../operator/delayWhen';
3+
4+
Observable.prototype.delayWhen = delayWhen;
5+
6+
export var _void: void;

0 commit comments

Comments
 (0)