Skip to content

Commit dfd95db

Browse files
feat(delayWhen): delayWhen's delayDurationSelector should support ObservableInput (#7049)
* feat(delayWhen): `delayWhen`'s `delayDurationSelector` should support `ObservableInput` * test(delayWhen): support Promises in delayWhen * chore: speed-up the tests
1 parent 61b877a commit dfd95db

File tree

4 files changed

+64
-19
lines changed

4 files changed

+64
-19
lines changed

spec-dtslint/operators/delayWhen-spec.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,24 @@ it('should support an empty notifier', () => {
1010
const o = of(1, 2, 3).pipe(delayWhen(() => NEVER)); // $ExpectType Observable<number>
1111
});
1212

13-
it('should support a subscriptiondelayWhen parameter', () => {
13+
it('should support a subscriptionDelay parameter', () => {
1414
const o = of(1, 2, 3).pipe(delayWhen(() => of('a', 'b', 'c'), of(new Date()))); // $ExpectType Observable<number>
1515
});
1616

1717
it('should enforce types', () => {
1818
const o = of(1, 2, 3).pipe(delayWhen()); // $ExpectError
1919
});
2020

21-
it('should enforce types of delayWhenDurationSelector', () => {
21+
it('should enforce types of delayDurationSelector', () => {
2222
const o = of(1, 2, 3).pipe(delayWhen(of('a', 'b', 'c'))); // $ExpectError
2323
const p = of(1, 2, 3).pipe(delayWhen((value: string, index) => of('a', 'b', 'c'))); // $ExpectError
2424
const q = of(1, 2, 3).pipe(delayWhen((value, index: string) => of('a', 'b', 'c'))); // $ExpectError
2525
});
2626

27-
it('should enforce types of subscriptiondelayWhen', () => {
27+
it('should enforce types of subscriptionDelay', () => {
2828
const o = of(1, 2, 3).pipe(delayWhen(() => of('a', 'b', 'c'), 'a')); // $ExpectError
2929
});
30+
31+
it('should support Promises', () => {
32+
const o = of(1, 2, 3).pipe(delayWhen(() => Promise.resolve('a'))); // $ExpectType Observable<number>
33+
});

spec/operators/audit-spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ describe('audit operator', () => {
395395
});
396396

397397
it('should audit by promise resolves', (done) => {
398-
const e1 = interval(10).pipe(take(5));
398+
const e1 = interval(1).pipe(take(5));
399399
const expected = [0, 1, 2, 3, 4];
400400

401401
e1.pipe(audit(() => Promise.resolve(42))).subscribe({
@@ -413,7 +413,7 @@ describe('audit operator', () => {
413413
});
414414

415415
it('should raise error when promise rejects', (done) => {
416-
const e1 = interval(10).pipe(take(10));
416+
const e1 = interval(1).pipe(take(10));
417417
const expected = [0, 1, 2];
418418
const error = new Error('error');
419419

spec/operators/delayWhen-spec.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { of, EMPTY } from 'rxjs';
1+
import { of, EMPTY, interval, take } from 'rxjs';
22
import { delayWhen, tap } from 'rxjs/operators';
33
import { TestScheduler } from 'rxjs/testing';
44
import { observableMatcher } from '../helpers/observableMatcher';
@@ -338,4 +338,42 @@ describe('delayWhen', () => {
338338
expectSubscriptions(e1.subscriptions).toBe(e1subs);
339339
});
340340
});
341+
342+
it('should delayWhen Promise resolves', (done) => {
343+
const e1 = interval(1).pipe(take(5));
344+
const expected = [0, 1, 2, 3, 4];
345+
346+
e1.pipe(delayWhen(() => Promise.resolve(42))).subscribe({
347+
next: (x: number) => {
348+
expect(x).to.equal(expected.shift());
349+
},
350+
error: () => {
351+
done(new Error('should not be called'));
352+
},
353+
complete: () => {
354+
expect(expected.length).to.equal(0);
355+
done();
356+
},
357+
});
358+
});
359+
360+
it('should raise error when Promise rejects', (done) => {
361+
const e1 = interval(1).pipe(take(10));
362+
const expected = [0, 1, 2];
363+
const error = new Error('err');
364+
365+
e1.pipe(delayWhen((x) => (x === 3 ? Promise.reject(error) : Promise.resolve(42)))).subscribe({
366+
next: (x: number) => {
367+
expect(x).to.equal(expected.shift());
368+
},
369+
error: (err: any) => {
370+
expect(err).to.be.an('error');
371+
expect(expected.length).to.equal(0);
372+
done();
373+
},
374+
complete: () => {
375+
done(new Error('should not be called'));
376+
},
377+
});
378+
});
341379
});

src/internal/operators/delayWhen.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import { Observable } from '../Observable';
2-
import { MonoTypeOperatorFunction } from '../types';
2+
import { MonoTypeOperatorFunction, ObservableInput } from '../types';
33
import { concat } from '../observable/concat';
44
import { take } from './take';
55
import { ignoreElements } from './ignoreElements';
66
import { mapTo } from './mapTo';
77
import { mergeMap } from './mergeMap';
8+
import { innerFrom } from '../observable/innerFrom';
89

910
/** @deprecated The `subscriptionDelay` parameter will be removed in v8. */
1011
export function delayWhen<T>(
11-
delayDurationSelector: (value: T, index: number) => Observable<any>,
12+
delayDurationSelector: (value: T, index: number) => ObservableInput<any>,
1213
subscriptionDelay: Observable<any>
1314
): MonoTypeOperatorFunction<T>;
14-
export function delayWhen<T>(delayDurationSelector: (value: T, index: number) => Observable<any>): MonoTypeOperatorFunction<T>;
15+
export function delayWhen<T>(delayDurationSelector: (value: T, index: number) => ObservableInput<any>): MonoTypeOperatorFunction<T>;
1516

1617
/**
1718
* Delays the emission of items from the source Observable by a given time span
@@ -26,8 +27,9 @@ export function delayWhen<T>(delayDurationSelector: (value: T, index: number) =>
2627
* a time span determined by another Observable. When the source emits a value,
2728
* the `delayDurationSelector` function is called with the value emitted from
2829
* the source Observable as the first argument to the `delayDurationSelector`.
29-
* The `delayDurationSelector` function should return an Observable, called
30-
* the "duration" Observable.
30+
* The `delayDurationSelector` function should return an {@link ObservableInput},
31+
* that is internally converted to an Observable that is called the "duration"
32+
* Observable.
3133
*
3234
* The source value is emitted on the output Observable only when the "duration"
3335
* Observable emits ({@link guide/glossary-and-semantics#next next}s) any value.
@@ -76,18 +78,19 @@ export function delayWhen<T>(delayDurationSelector: (value: T, index: number) =>
7678
* @see {@link audit}
7779
* @see {@link auditTime}
7880
*
79-
* @param {function(value: T, index: number): Observable} delayDurationSelector A function that
80-
* returns an Observable for each value emitted by the source Observable, which
81-
* is then used to delay the emission of that item on the output Observable
82-
* until the Observable returned from this function emits a value.
83-
* @param {Observable} subscriptionDelay An Observable that triggers the
84-
* subscription to the source Observable once it emits any value.
81+
* @param delayDurationSelector A function that returns an `ObservableInput` for
82+
* each `value` emitted by the source Observable, which is then used to delay the
83+
* emission of that `value` on the output Observable until the `ObservableInput`
84+
* returned from this function emits a next value. When called, beside `value`,
85+
* this function receives a zero-based `index` of the emission order.
86+
* @param subscriptionDelay An Observable that triggers the subscription to the
87+
* source Observable once it emits any value.
8588
* @return A function that returns an Observable that delays the emissions of
8689
* the source Observable by an amount of time specified by the Observable
8790
* returned by `delayDurationSelector`.
8891
*/
8992
export function delayWhen<T>(
90-
delayDurationSelector: (value: T, index: number) => Observable<any>,
93+
delayDurationSelector: (value: T, index: number) => ObservableInput<any>,
9194
subscriptionDelay?: Observable<any>
9295
): MonoTypeOperatorFunction<T> {
9396
if (subscriptionDelay) {
@@ -96,5 +99,5 @@ export function delayWhen<T>(
9699
concat(subscriptionDelay.pipe(take(1), ignoreElements()), source.pipe(delayWhen(delayDurationSelector)));
97100
}
98101

99-
return mergeMap((value, index) => delayDurationSelector(value, index).pipe(take(1), mapTo(value)));
102+
return mergeMap((value, index) => innerFrom(delayDurationSelector(value, index)).pipe(take(1), mapTo(value)));
100103
}

0 commit comments

Comments
 (0)