parent
d7920cae0a
commit
eb1730ba0c
|
@ -10,11 +10,12 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
node-version:
|
||||
- 18
|
||||
- 16
|
||||
- 14
|
||||
- 12
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm install
|
||||
|
|
|
@ -25,7 +25,7 @@ export type Options<ReturnType> = {
|
|||
|
||||
@example
|
||||
```
|
||||
import {setTimeout} from 'timers/promises';
|
||||
import {setTimeout} from 'node:timers/promises';
|
||||
import pTimeout from 'p-timeout';
|
||||
|
||||
const delayedPromise = () => setTimeout(200);
|
||||
|
@ -116,7 +116,7 @@ If you pass in a cancelable promise, specifically a promise with a `.cancel()` m
|
|||
|
||||
@example
|
||||
```
|
||||
import {setTimeout} from 'timers/promises';
|
||||
import {setTimeout} from 'node:timers/promises';
|
||||
import pTimeout from 'p-timeout';
|
||||
|
||||
const delayedPromise = () => setTimeout(200);
|
||||
|
|
32
index.js
32
index.js
|
@ -20,27 +20,32 @@ export class AbortError extends Error {
|
|||
/**
|
||||
TODO: Remove AbortError and just throw DOMException when targeting Node 18.
|
||||
*/
|
||||
const getDOMException = errorMessage => globalThis.DOMException === undefined ?
|
||||
new AbortError(errorMessage) :
|
||||
new DOMException(errorMessage);
|
||||
const getDOMException = errorMessage => globalThis.DOMException === undefined
|
||||
? new AbortError(errorMessage)
|
||||
: new DOMException(errorMessage);
|
||||
|
||||
/**
|
||||
TODO: Remove below function and just 'reject(signal.reason)' when targeting Node 18.
|
||||
*/
|
||||
const getAbortedReason = signal => {
|
||||
const reason = signal.reason === undefined ?
|
||||
getDOMException('This operation was aborted.') :
|
||||
signal.reason;
|
||||
const reason = signal.reason === undefined
|
||||
? getDOMException('This operation was aborted.')
|
||||
: signal.reason;
|
||||
|
||||
return reason instanceof Error ? reason : getDOMException(reason);
|
||||
};
|
||||
|
||||
export default function pTimeout(promise, options) {
|
||||
const {
|
||||
milliseconds,
|
||||
fallback,
|
||||
message,
|
||||
customTimers = {setTimeout, clearTimeout},
|
||||
} = options;
|
||||
|
||||
let timer;
|
||||
|
||||
const cancelablePromise = new Promise((resolve, reject) => {
|
||||
const {milliseconds, fallback, message} = options;
|
||||
|
||||
if (typeof milliseconds !== 'number' || Math.sign(milliseconds) !== 1) {
|
||||
throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``);
|
||||
}
|
||||
|
@ -50,11 +55,6 @@ export default function pTimeout(promise, options) {
|
|||
return;
|
||||
}
|
||||
|
||||
options = {
|
||||
customTimers: {setTimeout, clearTimeout},
|
||||
...options
|
||||
};
|
||||
|
||||
if (options.signal) {
|
||||
const {signal} = options;
|
||||
if (signal.aborted) {
|
||||
|
@ -66,7 +66,7 @@ export default function pTimeout(promise, options) {
|
|||
});
|
||||
}
|
||||
|
||||
timer = options.customTimers.setTimeout.call(undefined, () => {
|
||||
timer = customTimers.setTimeout.call(undefined, () => {
|
||||
if (fallback) {
|
||||
try {
|
||||
resolve(fallback());
|
||||
|
@ -93,13 +93,13 @@ export default function pTimeout(promise, options) {
|
|||
} catch (error) {
|
||||
reject(error);
|
||||
} finally {
|
||||
options.customTimers.clearTimeout.call(undefined, timer);
|
||||
customTimers.clearTimeout.call(undefined, timer);
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
cancelablePromise.clear = () => {
|
||||
clearTimeout(timer);
|
||||
customTimers.clearTimeout.call(undefined, timer);
|
||||
timer = undefined;
|
||||
};
|
||||
|
||||
|
|
|
@ -10,13 +10,15 @@ const delayedPromise: () => Promise<string> = async () => new Promise(resolve =>
|
|||
|
||||
pTimeout(delayedPromise(), {milliseconds: 50}).then(() => 'foo');
|
||||
pTimeout(delayedPromise(), {milliseconds: 50, fallback: async () => pTimeout(delayedPromise(), {milliseconds: 300})});
|
||||
pTimeout(delayedPromise(), {milliseconds: 50}).then(value => expectType<string>(value));
|
||||
pTimeout(delayedPromise(), {milliseconds: 50, message: 'error'}).then(value =>
|
||||
expectType<string>(value)
|
||||
);
|
||||
pTimeout(delayedPromise(), {milliseconds: 50, message: new Error('error')}).then(value =>
|
||||
expectType<string>(value)
|
||||
);
|
||||
pTimeout(delayedPromise(), {milliseconds: 50}).then(value => {
|
||||
expectType<string>(value);
|
||||
});
|
||||
pTimeout(delayedPromise(), {milliseconds: 50, message: 'error'}).then(value => {
|
||||
expectType<string>(value);
|
||||
});
|
||||
pTimeout(delayedPromise(), {milliseconds: 50, message: new Error('error')}).then(value => {
|
||||
expectType<string>(value);
|
||||
});
|
||||
pTimeout(delayedPromise(), {milliseconds: 50, fallback: async () => 10}).then(value => {
|
||||
expectType<string | number>(value);
|
||||
});
|
||||
|
@ -34,8 +36,8 @@ expectError(pTimeout(delayedPromise(), {
|
|||
milliseconds: 50,
|
||||
fallback: () => 10,
|
||||
customTimers: {
|
||||
setTimeout
|
||||
}
|
||||
setTimeout,
|
||||
},
|
||||
}));
|
||||
|
||||
expectError(pTimeout(delayedPromise(), {
|
||||
|
@ -43,8 +45,8 @@ expectError(pTimeout(delayedPromise(), {
|
|||
fallback: () => 10,
|
||||
customTimers: {
|
||||
setTimeout: () => 42, // Invalid `setTimeout` implementation
|
||||
clearTimeout
|
||||
}
|
||||
clearTimeout,
|
||||
},
|
||||
}));
|
||||
|
||||
expectError(pTimeout(delayedPromise(), {})); // `milliseconds` is required
|
||||
|
|
13
package.json
13
package.json
|
@ -12,8 +12,9 @@
|
|||
},
|
||||
"type": "module",
|
||||
"exports": "./index.js",
|
||||
"types": "./index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava && tsd"
|
||||
|
@ -36,12 +37,12 @@
|
|||
"bluebird"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "^3.15.0",
|
||||
"ava": "^4.3.1",
|
||||
"delay": "^5.0.0",
|
||||
"in-range": "^3.0.0",
|
||||
"p-cancelable": "^2.1.0",
|
||||
"time-span": "^4.0.0",
|
||||
"tsd": "^0.14.0",
|
||||
"xo": "^0.38.2"
|
||||
"p-cancelable": "^4.0.1",
|
||||
"time-span": "^5.1.0",
|
||||
"tsd": "^0.22.0",
|
||||
"xo": "^0.51.0"
|
||||
}
|
||||
}
|
||||
|
|
10
readme.md
10
readme.md
|
@ -4,14 +4,14 @@
|
|||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install p-timeout
|
||||
```sh
|
||||
npm install p-timeout
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import {setTimeout} from 'timers/promises';
|
||||
import {setTimeout} from 'node:timers/promises';
|
||||
import pTimeout from 'p-timeout';
|
||||
|
||||
const delayedPromise = setTimeout(200);
|
||||
|
@ -66,7 +66,7 @@ Do something other than rejecting with an error on timeout.
|
|||
You could for example retry:
|
||||
|
||||
```js
|
||||
import {setTimeout} from 'timers/promises';
|
||||
import {setTimeout} from 'node:timers/promises';
|
||||
import pTimeout from 'p-timeout';
|
||||
|
||||
const delayedPromise = () => setTimeout(200);
|
||||
|
@ -90,7 +90,7 @@ Useful for testing purposes, in particular to work around [`sinon.useFakeTimers(
|
|||
Example:
|
||||
|
||||
```js
|
||||
import {setTimeout} from 'timers/promises';
|
||||
import {setTimeout} from 'node:timers/promises';
|
||||
import pTimeout from 'p-timeout';
|
||||
|
||||
const originalSetTimeout = setTimeout;
|
||||
|
|
14
test.js
14
test.js
|
@ -27,7 +27,7 @@ test('throws when milliseconds is NaN', async t => {
|
|||
test('handles milliseconds being `Infinity`', async t => {
|
||||
t.is(
|
||||
await pTimeout(delay(50, {value: fixture}), {milliseconds: Number.POSITIVE_INFINITY}),
|
||||
fixture
|
||||
fixture,
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -77,8 +77,8 @@ test('accepts `customTimers` option', async t => {
|
|||
clearTimeout(timeoutId) {
|
||||
t.pass();
|
||||
return clearTimeout(timeoutId);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -101,13 +101,13 @@ if (globalThis.AbortController !== undefined) {
|
|||
|
||||
const promise = pTimeout(delay(3000), {
|
||||
milliseconds: 2000,
|
||||
signal: abortController.signal
|
||||
signal: abortController.signal,
|
||||
});
|
||||
|
||||
abortController.abort();
|
||||
|
||||
await t.throwsAsync(promise, {
|
||||
name: 'AbortError'
|
||||
name: 'AbortError',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -118,9 +118,9 @@ if (globalThis.AbortController !== undefined) {
|
|||
|
||||
await t.throwsAsync(pTimeout(delay(3000), {
|
||||
milliseconds: 2000,
|
||||
signal: abortController.signal
|
||||
signal: abortController.signal,
|
||||
}), {
|
||||
name: 'AbortError'
|
||||
name: 'AbortError',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue