Skip to content

Commit 2330c96

Browse files
danielwiehlbenlesh
andauthored
fix(timeout): no longer will timeout when receiving the first value synchronously (#6865)
* fix(timeout): do not timeout if source emits synchronously when subscribed Closes #6862 * chore: Improve comments * chore: minor test cleanup * chore: minor test cleanup * chore: Fix broken test that I broke! lol Co-authored-by: Ben Lesh <ben@benlesh.com>
1 parent 45a22e2 commit 2330c96

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

spec/operators/timeout-spec.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/** @prettier */
22
import { expect } from 'chai';
3-
import { timeout, mergeMap, take } from 'rxjs/operators';
3+
import { timeout, mergeMap, take, concatWith } from 'rxjs/operators';
44
import { TestScheduler } from 'rxjs/testing';
5-
import { TimeoutError, of, Observable } from 'rxjs';
5+
import { TimeoutError, of, Observable, NEVER } from 'rxjs';
66
import { observableMatcher } from '../helpers/observableMatcher';
77

88
/** @test {timeout} */
@@ -691,6 +691,15 @@ describe('timeout operator', () => {
691691
expectSubscriptions(inner.subscriptions).toBe([]);
692692
});
693693
});
694+
695+
it('should not timeout if source emits synchronously when subscribed', () => {
696+
rxTestScheduler.run(({ expectObservable, time }) => {
697+
const source = of('a').pipe(concatWith(NEVER));
698+
const t = time(' ---|');
699+
const expected = 'a---';
700+
expectObservable(source.pipe(timeout({ first: new Date(t) }))).toBe(expected);
701+
});
702+
});
694703
});
695704

696705
it('should stop listening to a synchronous observable when unsubscribed', () => {

src/internal/operators/timeout.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,10 +386,12 @@ export function timeout<T, O extends ObservableInput<any>, M>(
386386
);
387387

388388
// Intentionally terse code.
389+
// If we've `seen` a value, that means the "first" clause was met already, if it existed.
390+
// it also means that a timer was already started for "each" (in the next handler above).
389391
// If `first` was provided, and it's a number, then use it.
390392
// If `first` was provided and it's not a number, it's a Date, and we get the difference between it and "now".
391393
// If `first` was not provided at all, then our first timer will be the value from `each`.
392-
startTimer(first != null ? (typeof first === 'number' ? first : +first - scheduler!.now()) : each!);
394+
!seen && startTimer(first != null ? (typeof first === 'number' ? first : +first - scheduler!.now()) : each!);
393395
});
394396
}
395397

0 commit comments

Comments
 (0)