Skip to content

Commit d7920ca

Browse files
authored
Move the secondary parameters into the options parameter (#29)
1 parent de29542 commit d7920ca

File tree

5 files changed

+130
-101
lines changed

5 files changed

+130
-101
lines changed

index.d.ts

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,54 @@
1-
/* eslint-disable import/export */
2-
31
export class TimeoutError extends Error {
42
readonly name: 'TimeoutError';
53
constructor(message?: string);
64
}
75

8-
export interface ClearablePromise<T> extends Promise<T>{
6+
export interface ClearablePromise<T> extends Promise<T> {
97
/**
108
Clear the timeout.
119
*/
1210
clear: () => void;
1311
}
1412

15-
export type Options = {
13+
export type Options<ReturnType> = {
14+
/**
15+
Milliseconds before timing out.
16+
17+
Passing `Infinity` will cause it to never time out.
18+
*/
19+
milliseconds: number;
20+
21+
/**
22+
Do something other than rejecting with an error on timeout.
23+
24+
You could for example retry:
25+
26+
@example
27+
```
28+
import {setTimeout} from 'timers/promises';
29+
import pTimeout from 'p-timeout';
30+
31+
const delayedPromise = () => setTimeout(200);
32+
33+
await pTimeout(delayedPromise(), {
34+
milliseconds: 50,
35+
fallback: () => {
36+
return pTimeout(delayedPromise(), {
37+
milliseconds: 300
38+
});
39+
},
40+
});
41+
```
42+
*/
43+
fallback?: () => ReturnType | Promise<ReturnType>;
44+
45+
/**
46+
Specify a custom error message or error.
47+
48+
If you do a custom error, it's recommended to sub-class `pTimeout.TimeoutError`.
49+
*/
50+
message?: string | Error;
51+
1652
/**
1753
Custom implementations for the `setTimeout` and `clearTimeout` functions.
1854
@@ -29,7 +65,8 @@ export type Options = {
2965
sinon.useFakeTimers();
3066
3167
// Use `pTimeout` without being affected by `sinon.useFakeTimers()`:
32-
await pTimeout(doSomething(), 2000, undefined, {
68+
await pTimeout(doSomething(), {
69+
milliseconds: 2000,
3370
customTimers: {
3471
setTimeout: originalSetTimeout,
3572
clearTimeout: originalClearTimeout
@@ -38,8 +75,8 @@ export type Options = {
3875
```
3976
*/
4077
readonly customTimers?: {
41-
setTimeout: typeof global.setTimeout;
42-
clearTimeout: typeof global.clearTimeout;
78+
setTimeout: typeof globalThis.setTimeout;
79+
clearTimeout: typeof globalThis.clearTimeout;
4380
};
4481

4582
/**
@@ -60,7 +97,8 @@ export type Options = {
6097
abortController.abort();
6198
}, 100);
6299
63-
await pTimeout(delayedPromise, 2000, undefined, {
100+
await pTimeout(delayedPromise, {
101+
milliseconds: 2000,
64102
signal: abortController.signal
65103
});
66104
```
@@ -74,36 +112,6 @@ Timeout a promise after a specified amount of time.
74112
If you pass in a cancelable promise, specifically a promise with a `.cancel()` method, that method will be called when the `pTimeout` promise times out.
75113
76114
@param input - Promise to decorate.
77-
@param milliseconds - Milliseconds before timing out.
78-
@param message - Specify a custom error message or error. If you do a custom error, it's recommended to sub-class `pTimeout.TimeoutError`. Default: `'Promise timed out after 50 milliseconds'`.
79-
@returns A decorated `input` that times out after `milliseconds` time. It has a `.clear()` method that clears the timeout.
80-
81-
@example
82-
```
83-
import {setTimeout} from 'timers/promises';
84-
import pTimeout from 'p-timeout';
85-
86-
const delayedPromise = setTimeout(200);
87-
88-
await pTimeout(delayedPromise, 50);
89-
//=> [TimeoutError: Promise timed out after 50 milliseconds]
90-
```
91-
*/
92-
export default function pTimeout<ValueType>(
93-
input: PromiseLike<ValueType>,
94-
milliseconds: number,
95-
message?: string | Error,
96-
options?: Options
97-
): ClearablePromise<ValueType>;
98-
99-
/**
100-
Timeout a promise after a specified amount of time.
101-
102-
If you pass in a cancelable promise, specifically a promise with a `.cancel()` method, that method will be called when the `pTimeout` promise times out.
103-
104-
@param input - Promise to decorate.
105-
@param milliseconds - Milliseconds before timing out. Passing `Infinity` will cause it to never time out.
106-
@param fallback - Do something other than rejecting with an error on timeout. You could for example retry.
107115
@returns A decorated `input` that times out after `milliseconds` time. It has a `.clear()` method that clears the timeout.
108116
109117
@example
@@ -113,14 +121,15 @@ import pTimeout from 'p-timeout';
113121
114122
const delayedPromise = () => setTimeout(200);
115123
116-
await pTimeout(delayedPromise(), 50, () => {
117-
return pTimeout(delayedPromise(), 300);
124+
await pTimeout(delayedPromise(), {
125+
milliseconds: 50,
126+
fallback: () => {
127+
return pTimeout(delayedPromise(), 300);
128+
}
118129
});
119130
```
120131
*/
121-
export default function pTimeout<ValueType, ReturnType>(
132+
export default function pTimeout<ValueType, ReturnType = ValueType>(
122133
input: PromiseLike<ValueType>,
123-
milliseconds: number,
124-
fallback: () => ReturnType | Promise<ReturnType>,
125-
options?: Options
134+
options: Options<ReturnType>
126135
): ClearablePromise<ValueType | ReturnType>;

index.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ const getAbortedReason = signal => {
3535
return reason instanceof Error ? reason : getDOMException(reason);
3636
};
3737

38-
export default function pTimeout(promise, milliseconds, fallback, options) {
38+
export default function pTimeout(promise, options) {
3939
let timer;
4040

4141
const cancelablePromise = new Promise((resolve, reject) => {
42+
const {milliseconds, fallback, message} = options;
43+
4244
if (typeof milliseconds !== 'number' || Math.sign(milliseconds) !== 1) {
4345
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
4446
}
@@ -65,7 +67,7 @@ export default function pTimeout(promise, milliseconds, fallback, options) {
6567
}
6668

6769
timer = options.customTimers.setTimeout.call(undefined, () => {
68-
if (typeof fallback === 'function') {
70+
if (fallback) {
6971
try {
7072
resolve(fallback());
7173
} catch (error) {
@@ -75,8 +77,8 @@ export default function pTimeout(promise, milliseconds, fallback, options) {
7577
return;
7678
}
7779

78-
const message = typeof fallback === 'string' ? fallback : `Promise timed out after ${milliseconds} milliseconds`;
79-
const timeoutError = fallback instanceof Error ? fallback : new TimeoutError(message);
80+
const errorMessage = typeof message === 'string' ? message : `Promise timed out after ${milliseconds} milliseconds`;
81+
const timeoutError = message instanceof Error ? message : new TimeoutError(errorMessage);
8082

8183
if (typeof promise.cancel === 'function') {
8284
promise.cancel();

index.test-d.ts

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,52 @@
22
import {expectType, expectError} from 'tsd';
33
import pTimeout, {TimeoutError} from './index.js';
44

5-
const delayedPromise: () => Promise<string> = async () => {
6-
return new Promise(resolve => {
7-
setTimeout(() => {
8-
resolve('foo');
9-
}, 200);
10-
});
11-
};
12-
13-
pTimeout(delayedPromise(), 50).then(() => 'foo');
14-
pTimeout(delayedPromise(), 50, async () => {
15-
return pTimeout(delayedPromise(), 300);
5+
const delayedPromise: () => Promise<string> = async () => new Promise(resolve => {
6+
setTimeout(() => {
7+
resolve('foo');
8+
}, 200);
169
});
17-
pTimeout(delayedPromise(), 50).then(value => expectType<string>(value));
18-
pTimeout(delayedPromise(), 50, 'error').then(value =>
10+
11+
pTimeout(delayedPromise(), {milliseconds: 50}).then(() => 'foo');
12+
pTimeout(delayedPromise(), {milliseconds: 50, fallback: async () => pTimeout(delayedPromise(), {milliseconds: 300})});
13+
pTimeout(delayedPromise(), {milliseconds: 50}).then(value => expectType<string>(value));
14+
pTimeout(delayedPromise(), {milliseconds: 50, message: 'error'}).then(value =>
1915
expectType<string>(value)
2016
);
21-
pTimeout(delayedPromise(), 50, new Error('error')).then(value =>
17+
pTimeout(delayedPromise(), {milliseconds: 50, message: new Error('error')}).then(value =>
2218
expectType<string>(value)
2319
);
24-
pTimeout(delayedPromise(), 50, async () => 10).then(value => {
20+
pTimeout(delayedPromise(), {milliseconds: 50, fallback: async () => 10}).then(value => {
2521
expectType<string | number>(value);
2622
});
27-
pTimeout(delayedPromise(), 50, () => 10).then(value => {
23+
pTimeout(delayedPromise(), {milliseconds: 50, fallback: () => 10}).then(value => {
2824
expectType<string | number>(value);
2925
});
3026

3127
const customTimers = {setTimeout, clearTimeout};
32-
pTimeout(delayedPromise(), 50, undefined, {customTimers});
33-
pTimeout(delayedPromise(), 50, 'foo', {customTimers});
34-
pTimeout(delayedPromise(), 50, new Error('error'), {customTimers});
35-
pTimeout(delayedPromise(), 50, () => 10, {});
28+
pTimeout(delayedPromise(), {milliseconds: 50, customTimers});
29+
pTimeout(delayedPromise(), {milliseconds: 50, message: 'foo', customTimers});
30+
pTimeout(delayedPromise(), {milliseconds: 50, message: new Error('error'), customTimers});
31+
pTimeout(delayedPromise(), {milliseconds: 50, fallback: () => 10});
3632

37-
expectError(pTimeout(delayedPromise(), 50, () => 10, {customTimers: {setTimeout}}));
38-
expectError(pTimeout(delayedPromise(), 50, () => 10, {
33+
expectError(pTimeout(delayedPromise(), {
34+
milliseconds: 50,
35+
fallback: () => 10,
36+
customTimers: {
37+
setTimeout
38+
}
39+
}));
40+
41+
expectError(pTimeout(delayedPromise(), {
42+
milliseconds: 50,
43+
fallback: () => 10,
3944
customTimers: {
4045
setTimeout: () => 42, // Invalid `setTimeout` implementation
4146
clearTimeout
4247
}
4348
}));
4449

50+
expectError(pTimeout(delayedPromise(), {})); // `milliseconds` is required
51+
4552
const timeoutError = new TimeoutError();
4653
expectType<TimeoutError>(timeoutError);

readme.md

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ import pTimeout from 'p-timeout';
1616

1717
const delayedPromise = setTimeout(200);
1818

19-
await pTimeout(delayedPromise, 50);
19+
await pTimeout(delayedPromise, {
20+
milliseconds: 50,
21+
});
2022
//=> [TimeoutError: Promise timed out after 50 milliseconds]
2123
```
2224

2325
## API
2426

25-
### pTimeout(input, milliseconds, message?, options?)
26-
### pTimeout(input, milliseconds, fallback?, options?)
27+
### pTimeout(input, options)
2728

2829
Returns a decorated `input` that times out after `milliseconds` time. It has a `.clear()` method that clears the timeout.
2930

@@ -35,15 +36,19 @@ Type: `Promise`
3536

3637
Promise to decorate.
3738

38-
#### milliseconds
39+
#### options
40+
41+
Type: `object`
42+
43+
##### milliseconds
3944

4045
Type: `number`
4146

4247
Milliseconds before timing out.
4348

4449
Passing `Infinity` will cause it to never time out.
4550

46-
#### message
51+
##### message
4752

4853
Type: `string | Error`\
4954
Default: `'Promise timed out after 50 milliseconds'`
@@ -52,7 +57,7 @@ Specify a custom error message or error.
5257

5358
If you do a custom error, it's recommended to sub-class `pTimeout.TimeoutError`.
5459

55-
#### fallback
60+
##### fallback
5661

5762
Type: `Function`
5863

@@ -66,15 +71,14 @@ import pTimeout from 'p-timeout';
6671

6772
const delayedPromise = () => setTimeout(200);
6873

69-
await pTimeout(delayedPromise(), 50, () => {
70-
return pTimeout(delayedPromise(), 300);
74+
await pTimeout(delayedPromise(), {
75+
milliseconds: 50,
76+
fallback: () => {
77+
return pTimeout(delayedPromise(), 300);
78+
},
7179
});
7280
```
7381

74-
#### options
75-
76-
Type: `object`
77-
7882
##### customTimers
7983

8084
Type: `object` with function properties `setTimeout` and `clearTimeout`
@@ -95,7 +99,8 @@ const originalClearTimeout = clearTimeout;
9599
sinon.useFakeTimers();
96100

97101
// Use `pTimeout` without being affected by `sinon.useFakeTimers()`:
98-
await pTimeout(doSomething(), 2000, undefined, {
102+
await pTimeout(doSomething(), {
103+
milliseconds: 2000,
99104
customTimers: {
100105
setTimeout: originalSetTimeout,
101106
clearTimeout: originalClearTimeout
@@ -123,7 +128,8 @@ setTimeout(() => {
123128
abortController.abort();
124129
}, 100);
125130

126-
await pTimeout(delayedPromise, 2000, undefined, {
131+
await pTimeout(delayedPromise, {
132+
milliseconds: 2000,
127133
signal: abortController.signal
128134
});
129135
```

0 commit comments

Comments
 (0)