Skip to content

Commit

Permalink
refactoring timeout + tests
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaly-t committed Aug 3, 2024
1 parent 2c04859 commit d0a0570
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 19 deletions.
7 changes: 6 additions & 1 deletion src/ops/async/delay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {$A, Operation, IterationState} from '../../types';
import {createOperation, throwOnSync} from '../../utils';

/**
* Delays each value by the specified timeout.
* Delays each value by the specified timeout (including the first one).
* When the timeout is a negative number, no delay added.
*
* ```ts
Expand All @@ -20,6 +20,11 @@ import {createOperation, throwOnSync} from '../../utils';
* }
* ```
*
* Note that passing in `timeout = 0`, or returning the same from the callback,
* still uses the `timeout` function, just like `setTimeout(0)`, which can be used
* for throttling. In order to fully deactivate it, you need to pass in a negative
* `timeout` value.
*
* @throws `Error: 'Operator "delay" requires asynchronous pipeline'` when used inside a synchronous pipeline.
*
* @see
Expand Down
16 changes: 8 additions & 8 deletions src/ops/timeout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ function timeoutSync<T>(
ms: number,
cb?: (count: number) => void
): Iterable<T> {
if (ms < 0) {
// timeout is inactive, reuse the source iterable instead:
return iterable;
}
return {
[$S](): Iterator<T> {
const i = iterable[$S]();
if (ms < 0) {
// timeout is inactive;
return i;
}
let count = 0; // number of items processed
let start: number;
let done = false;
Expand Down Expand Up @@ -113,13 +113,13 @@ function timeoutAsync<T>(
ms: number,
cb?: (index: number) => void
): AsyncIterable<T> {
if (ms < 0) {
// timeout is inactive, reuse the source iterable instead:
return iterable;
}
return {
[$A](): AsyncIterator<T> {
const i = iterable[$A]();
if (ms < 0) {
// timeout is inactive;
return i;
}
let count = 0; // number of items processed
let done = false;
const resolutions: ((res: IteratorResult<any>) => void)[] = [];
Expand Down
42 changes: 32 additions & 10 deletions test/ops/timeout/async.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
import {_asyncValues, expect} from '../../header';
import {pipeAsync, delay, timeout, tap} from '../../../src';
import {
pipeAsync,
delay,
timeout,
tap,
IterationState,
Operation
} from '../../../src';

export default () => {
it('must end iteration after timeout', async () => {
const i = pipeAsync([1, 2, 3], delay(10), timeout(35));
const i = pipeAsync([1, 2, 3], interval(10), timeout(19));
expect(await _asyncValues(i)).to.eql([1, 2]);
});
it('must emit nothing when timeout does not permit', async () => {
let count: any;
const i = pipeAsync(
[1, 2, 3],
delay(10),
timeout(1, (c) => {
[11, 22, 33],
interval(10),
timeout(3, (c) => {
count = c;
})
);
expect(await _asyncValues(i)).to.eql([]);
expect(count).to.eql(0);
expect(await _asyncValues(i)).to.eql([11]);
expect(count).to.eql(1);
});
it('must invoke callback on timeout', async () => {
let count;
const i = pipeAsync(
[1, 2, 3],
delay(10),
timeout(29, (c) => {
interval(10),
timeout(19, (c) => {
count = c;
})
);
Expand All @@ -49,7 +56,7 @@ export default () => {
let e: any;
const i = pipeAsync(
[1, 2, 3],
delay(10),
interval(10),
timeout(1, () => {
throw new Error('timeout');
})
Expand Down Expand Up @@ -80,3 +87,18 @@ export default () => {
expect(count).to.be.undefined;
});
};

/**
* Helper borrowed from iter-ops-extras, to avoid delaying first value in tests;
* https://github.com/vitaly-t/iter-ops-extras/blob/main/src/interval.ts
*/
function interval<T>(
timeout:
| number
| ((value: T, index: number, state: IterationState) => number)
): Operation<T, T> {
if (typeof timeout === 'function') {
return delay((v, i, s) => (i ? timeout(v, i, s) : -1));
}
return delay((_, i) => (i ? timeout : -1));
}

0 comments on commit d0a0570

Please sign in to comment.