Require Node.js 12 and move to ESM
This commit is contained in:
parent
4f86930f75
commit
458618efa4
|
@ -1,3 +0,0 @@
|
||||||
github: sindresorhus
|
|
||||||
open_collective: sindresorhus
|
|
||||||
custom: https://sindresorhus.com/donate
|
|
|
@ -12,7 +12,6 @@ jobs:
|
||||||
node-version:
|
node-version:
|
||||||
- 14
|
- 14
|
||||||
- 12
|
- 12
|
||||||
- 10
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
|
|
|
@ -1,113 +1,101 @@
|
||||||
declare class TimeoutErrorClass extends Error {
|
/* eslint-disable import/export */
|
||||||
|
|
||||||
|
export class TimeoutError extends Error {
|
||||||
readonly name: 'TimeoutError';
|
readonly name: 'TimeoutError';
|
||||||
constructor(message?: string);
|
constructor(message?: string);
|
||||||
}
|
}
|
||||||
|
|
||||||
declare namespace pTimeout {
|
export interface ClearablePromise<T> extends Promise<T>{
|
||||||
type TimeoutError = TimeoutErrorClass;
|
|
||||||
|
|
||||||
type Options = {
|
|
||||||
/**
|
|
||||||
Custom implementations for the `setTimeout` and `clearTimeout` functions.
|
|
||||||
|
|
||||||
Useful for testing purposes, in particular to work around [`sinon.useFakeTimers()`](https://sinonjs.org/releases/latest/fake-timers/).
|
|
||||||
|
|
||||||
@example
|
|
||||||
```
|
|
||||||
import pTimeout = require('p-timeout');
|
|
||||||
import sinon = require('sinon');
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
const originalSetTimeout = setTimeout;
|
|
||||||
const originalClearTimeout = clearTimeout;
|
|
||||||
|
|
||||||
sinon.useFakeTimers();
|
|
||||||
|
|
||||||
// Use `pTimeout` without being affected by `sinon.useFakeTimers()`:
|
|
||||||
await pTimeout(doSomething(), 2000, undefined, {
|
|
||||||
customTimers: {
|
|
||||||
setTimeout: originalSetTimeout,
|
|
||||||
clearTimeout: originalClearTimeout
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
```
|
|
||||||
*/
|
|
||||||
readonly customTimers?: {
|
|
||||||
setTimeout: typeof global.setTimeout;
|
|
||||||
clearTimeout: typeof global.clearTimeout;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ClearablePromise<T> extends Promise<T>{
|
|
||||||
/**
|
/**
|
||||||
Clear the timeout.
|
Clear the timeout.
|
||||||
*/
|
*/
|
||||||
clear: () => void;
|
clear: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare const pTimeout: {
|
export type Options = {
|
||||||
TimeoutError: typeof TimeoutErrorClass;
|
|
||||||
|
|
||||||
default: typeof pTimeout;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Timeout a promise after a specified amount of time.
|
Custom implementations for the `setTimeout` and `clearTimeout` functions.
|
||||||
|
|
||||||
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.
|
Useful for testing purposes, in particular to work around [`sinon.useFakeTimers()`](https://sinonjs.org/releases/latest/fake-timers/).
|
||||||
|
|
||||||
@param input - Promise to decorate.
|
|
||||||
@param milliseconds - Milliseconds before timing out.
|
|
||||||
@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'`.
|
|
||||||
@returns A decorated `input` that times out after `milliseconds` time. It has a `.clear()` method that clears the timeout.
|
|
||||||
|
|
||||||
@example
|
@example
|
||||||
```
|
```
|
||||||
import delay = require('delay');
|
import pTimeout from 'p-timeout';
|
||||||
import pTimeout = require('p-timeout');
|
import sinon from 'sinon';
|
||||||
|
|
||||||
const delayedPromise = delay(200);
|
const originalSetTimeout = setTimeout;
|
||||||
|
const originalClearTimeout = clearTimeout;
|
||||||
|
|
||||||
pTimeout(delayedPromise, 50).then(() => 'foo');
|
sinon.useFakeTimers();
|
||||||
//=> [TimeoutError: Promise timed out after 50 milliseconds]
|
|
||||||
```
|
|
||||||
*/
|
|
||||||
<ValueType>(
|
|
||||||
input: PromiseLike<ValueType>,
|
|
||||||
milliseconds: number,
|
|
||||||
message?: string | Error,
|
|
||||||
options?: pTimeout.Options
|
|
||||||
): ClearablePromise<ValueType>;
|
|
||||||
|
|
||||||
/**
|
// Use `pTimeout` without being affected by `sinon.useFakeTimers()`:
|
||||||
Timeout a promise after a specified amount of time.
|
await pTimeout(doSomething(), 2000, undefined, {
|
||||||
|
customTimers: {
|
||||||
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.
|
setTimeout: originalSetTimeout,
|
||||||
|
clearTimeout: originalClearTimeout
|
||||||
@param input - Promise to decorate.
|
}
|
||||||
@param milliseconds - Milliseconds before timing out. Passing `Infinity` will cause it to never time out.
|
|
||||||
@param fallback - Do something other than rejecting with an error on timeout. You could for example retry.
|
|
||||||
@returns A decorated `input` that times out after `milliseconds` time. It has a `.clear()` method that clears the timeout.
|
|
||||||
|
|
||||||
@example
|
|
||||||
```
|
|
||||||
import delay = require('delay');
|
|
||||||
import pTimeout = require('p-timeout');
|
|
||||||
|
|
||||||
const delayedPromise = () => delay(200);
|
|
||||||
|
|
||||||
pTimeout(delayedPromise(), 50, () => {
|
|
||||||
return pTimeout(delayedPromise(), 300);
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
<ValueType, ReturnType>(
|
readonly customTimers?: {
|
||||||
input: PromiseLike<ValueType>,
|
setTimeout: typeof global.setTimeout;
|
||||||
milliseconds: number,
|
clearTimeout: typeof global.clearTimeout;
|
||||||
fallback: () => ReturnType | Promise<ReturnType>,
|
};
|
||||||
options?: pTimeout.Options
|
|
||||||
): ClearablePromise<ValueType | ReturnType>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export = pTimeout;
|
/**
|
||||||
|
Timeout a promise after a specified amount of time.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param input - Promise to decorate.
|
||||||
|
@param milliseconds - Milliseconds before timing out.
|
||||||
|
@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'`.
|
||||||
|
@returns A decorated `input` that times out after `milliseconds` time. It has a `.clear()` method that clears the timeout.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import {setTimeout} from 'timers/promises';
|
||||||
|
import pTimeout from 'p-timeout';
|
||||||
|
|
||||||
|
const delayedPromise = setTimeout(200);
|
||||||
|
|
||||||
|
await pTimeout(delayedPromise, 50);
|
||||||
|
//=> [TimeoutError: Promise timed out after 50 milliseconds]
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
export default function pTimeout<ValueType>(
|
||||||
|
input: PromiseLike<ValueType>,
|
||||||
|
milliseconds: number,
|
||||||
|
message?: string | Error,
|
||||||
|
options?: Options
|
||||||
|
): ClearablePromise<ValueType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Timeout a promise after a specified amount of time.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param input - Promise to decorate.
|
||||||
|
@param milliseconds - Milliseconds before timing out. Passing `Infinity` will cause it to never time out.
|
||||||
|
@param fallback - Do something other than rejecting with an error on timeout. You could for example retry.
|
||||||
|
@returns A decorated `input` that times out after `milliseconds` time. It has a `.clear()` method that clears the timeout.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import {setTimeout} from 'timers/promises';
|
||||||
|
import pTimeout from 'p-timeout';
|
||||||
|
|
||||||
|
const delayedPromise = () => setTimeout(200);
|
||||||
|
|
||||||
|
await pTimeout(delayedPromise(), 50, () => {
|
||||||
|
return pTimeout(delayedPromise(), 300);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
export default function pTimeout<ValueType, ReturnType>(
|
||||||
|
input: PromiseLike<ValueType>,
|
||||||
|
milliseconds: number,
|
||||||
|
fallback: () => ReturnType | Promise<ReturnType>,
|
||||||
|
options?: Options
|
||||||
|
): ClearablePromise<ValueType | ReturnType>;
|
||||||
|
|
16
index.js
16
index.js
|
@ -1,20 +1,18 @@
|
||||||
'use strict';
|
export class TimeoutError extends Error {
|
||||||
|
|
||||||
class TimeoutError extends Error {
|
|
||||||
constructor(message) {
|
constructor(message) {
|
||||||
super(message);
|
super(message);
|
||||||
this.name = 'TimeoutError';
|
this.name = 'TimeoutError';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pTimeout = (promise, milliseconds, fallback, options) => {
|
export default function pTimeout(promise, milliseconds, fallback, options) {
|
||||||
let timer;
|
let timer;
|
||||||
const cancelablePromise = new Promise((resolve, reject) => {
|
const cancelablePromise = new Promise((resolve, reject) => {
|
||||||
if (typeof milliseconds !== 'number' || milliseconds < 0) {
|
if (typeof milliseconds !== 'number' || milliseconds < 0) {
|
||||||
throw new TypeError('Expected `milliseconds` to be a positive number');
|
throw new TypeError('Expected `milliseconds` to be a positive number');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (milliseconds === Infinity) {
|
if (milliseconds === Number.POSITIVE_INFINITY) {
|
||||||
resolve(promise);
|
resolve(promise);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -62,10 +60,4 @@ const pTimeout = (promise, milliseconds, fallback, options) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return cancelablePromise;
|
return cancelablePromise;
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = pTimeout;
|
|
||||||
// TODO: Remove this for the next major release
|
|
||||||
module.exports.default = pTimeout;
|
|
||||||
|
|
||||||
module.exports.TimeoutError = TimeoutError;
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||||
import {expectType, expectError} from 'tsd';
|
import {expectType, expectError} from 'tsd';
|
||||||
import pTimeout = require('.');
|
import pTimeout, {TimeoutError} from './index.js';
|
||||||
import {TimeoutError} from '.';
|
|
||||||
|
|
||||||
const delayedPromise: () => Promise<string> = async () => {
|
const delayedPromise: () => Promise<string> = async () => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
@ -11,7 +11,7 @@ const delayedPromise: () => Promise<string> = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
pTimeout(delayedPromise(), 50).then(() => 'foo');
|
pTimeout(delayedPromise(), 50).then(() => 'foo');
|
||||||
pTimeout(delayedPromise(), 50, () => {
|
pTimeout(delayedPromise(), 50, async () => {
|
||||||
return pTimeout(delayedPromise(), 300);
|
return pTimeout(delayedPromise(), 300);
|
||||||
});
|
});
|
||||||
pTimeout(delayedPromise(), 50).then(value => expectType<string>(value));
|
pTimeout(delayedPromise(), 50).then(value => expectType<string>(value));
|
||||||
|
|
19
package.json
19
package.json
|
@ -4,13 +4,16 @@
|
||||||
"description": "Timeout a promise after a specified amount of time",
|
"description": "Timeout a promise after a specified amount of time",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "sindresorhus/p-timeout",
|
"repository": "sindresorhus/p-timeout",
|
||||||
|
"funding": "https://github.com/sponsors/sindresorhus",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Sindre Sorhus",
|
"name": "Sindre Sorhus",
|
||||||
"email": "sindresorhus@gmail.com",
|
"email": "sindresorhus@gmail.com",
|
||||||
"url": "https://sindresorhus.com"
|
"url": "https://sindresorhus.com"
|
||||||
},
|
},
|
||||||
|
"type": "module",
|
||||||
|
"exports": "./index.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "xo && ava && tsd"
|
"test": "xo && ava && tsd"
|
||||||
|
@ -33,12 +36,12 @@
|
||||||
"bluebird"
|
"bluebird"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ava": "^2.4.0",
|
"ava": "^3.15.0",
|
||||||
"delay": "^4.4.0",
|
"delay": "^5.0.0",
|
||||||
"p-cancelable": "^2.0.0",
|
"in-range": "^3.0.0",
|
||||||
"tsd": "^0.13.1",
|
"p-cancelable": "^2.1.0",
|
||||||
"xo": "^0.35.0",
|
"time-span": "^4.0.0",
|
||||||
"in-range": "^2.0.0",
|
"tsd": "^0.14.0",
|
||||||
"time-span": "^4.0.0"
|
"xo": "^0.38.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
42
readme.md
42
readme.md
|
@ -11,12 +11,12 @@ $ npm install p-timeout
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const delay = require('delay');
|
import {setTimeout} from 'timers/promises';
|
||||||
const pTimeout = require('p-timeout');
|
import pTimeout from 'p-timeout';
|
||||||
|
|
||||||
const delayedPromise = delay(200);
|
const delayedPromise = setTimeout(200);
|
||||||
|
|
||||||
pTimeout(delayedPromise, 50).then(() => 'foo');
|
await pTimeout(delayedPromise, 50);
|
||||||
//=> [TimeoutError: Promise timed out after 50 milliseconds]
|
//=> [TimeoutError: Promise timed out after 50 milliseconds]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -61,12 +61,12 @@ Do something other than rejecting with an error on timeout.
|
||||||
You could for example retry:
|
You could for example retry:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const delay = require('delay');
|
import {setTimeout} from 'timers/promises';
|
||||||
const pTimeout = require('p-timeout');
|
import pTimeout from 'p-timeout';
|
||||||
|
|
||||||
const delayedPromise = () => delay(200);
|
const delayedPromise = () => setTimeout(200);
|
||||||
|
|
||||||
pTimeout(delayedPromise(), 50, () => {
|
await pTimeout(delayedPromise(), 50, () => {
|
||||||
return pTimeout(delayedPromise(), 300);
|
return pTimeout(delayedPromise(), 300);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -86,23 +86,21 @@ Useful for testing purposes, in particular to work around [`sinon.useFakeTimers(
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const pTimeout = require('p-timeout');
|
import {setTimeout} from 'timers/promises';
|
||||||
const sinon = require('sinon');
|
import pTimeout from 'p-timeout';
|
||||||
|
|
||||||
(async () => {
|
const originalSetTimeout = setTimeout;
|
||||||
const originalSetTimeout = setTimeout;
|
const originalClearTimeout = clearTimeout;
|
||||||
const originalClearTimeout = clearTimeout;
|
|
||||||
|
|
||||||
sinon.useFakeTimers();
|
sinon.useFakeTimers();
|
||||||
|
|
||||||
// Use `pTimeout` without being affected by `sinon.useFakeTimers()`:
|
// Use `pTimeout` without being affected by `sinon.useFakeTimers()`:
|
||||||
await pTimeout(doSomething(), 2000, undefined, {
|
await pTimeout(doSomething(), 2000, undefined, {
|
||||||
customTimers: {
|
customTimers: {
|
||||||
setTimeout: originalSetTimeout,
|
setTimeout: originalSetTimeout,
|
||||||
clearTimeout: originalClearTimeout
|
clearTimeout: originalClearTimeout
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### pTimeout.TimeoutError
|
### pTimeout.TimeoutError
|
||||||
|
|
22
test.js
22
test.js
|
@ -3,7 +3,7 @@ import delay from 'delay';
|
||||||
import PCancelable from 'p-cancelable';
|
import PCancelable from 'p-cancelable';
|
||||||
import inRange from 'in-range';
|
import inRange from 'in-range';
|
||||||
import timeSpan from 'time-span';
|
import timeSpan from 'time-span';
|
||||||
import pTimeout from '.';
|
import pTimeout, {TimeoutError} from './index.js';
|
||||||
|
|
||||||
const fixture = Symbol('fixture');
|
const fixture = Symbol('fixture');
|
||||||
const fixtureError = new Error('fixture');
|
const fixtureError = new Error('fixture');
|
||||||
|
@ -13,35 +13,35 @@ test('resolves before timeout', async t => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('throws when milliseconds is not number', async t => {
|
test('throws when milliseconds is not number', async t => {
|
||||||
await t.throwsAsync(pTimeout(delay(50), '200'), TypeError);
|
await t.throwsAsync(pTimeout(delay(50), '200'), {instanceOf: TypeError});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('throws when milliseconds is negative number', async t => {
|
test('throws when milliseconds is negative number', async t => {
|
||||||
await t.throwsAsync(pTimeout(delay(50), -1), TypeError);
|
await t.throwsAsync(pTimeout(delay(50), -1), {instanceOf: TypeError});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handles milliseconds being `Infinity`', async t => {
|
test('handles milliseconds being `Infinity`', async t => {
|
||||||
t.is(
|
t.is(
|
||||||
await pTimeout(delay(50, {value: fixture}), Infinity),
|
await pTimeout(delay(50, {value: fixture}), Number.POSITIVE_INFINITY),
|
||||||
fixture
|
fixture
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('rejects after timeout', async t => {
|
test('rejects after timeout', async t => {
|
||||||
await t.throwsAsync(pTimeout(delay(200), 50), pTimeout.TimeoutError);
|
await t.throwsAsync(pTimeout(delay(200), 50), {instanceOf: TimeoutError});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('rejects before timeout if specified promise rejects', async t => {
|
test('rejects before timeout if specified promise rejects', async t => {
|
||||||
await t.throwsAsync(pTimeout(delay(50).then(() => Promise.reject(fixtureError)), 200), fixtureError.message);
|
await t.throwsAsync(pTimeout(delay(50).then(() => Promise.reject(fixtureError)), 200), {message: fixtureError.message});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('fallback argument', async t => {
|
test('fallback argument', async t => {
|
||||||
await t.throwsAsync(pTimeout(delay(200), 50, 'rainbow'), 'rainbow');
|
await t.throwsAsync(pTimeout(delay(200), 50, 'rainbow'), {message: 'rainbow'});
|
||||||
await t.throwsAsync(pTimeout(delay(200), 50, new RangeError('cake')), RangeError);
|
await t.throwsAsync(pTimeout(delay(200), 50, new RangeError('cake')), {instanceOf: RangeError});
|
||||||
await t.throwsAsync(pTimeout(delay(200), 50, () => Promise.reject(fixtureError)), fixtureError.message);
|
await t.throwsAsync(pTimeout(delay(200), 50, () => Promise.reject(fixtureError)), {message: fixtureError.message});
|
||||||
await t.throwsAsync(pTimeout(delay(200), 50, () => {
|
await t.throwsAsync(pTimeout(delay(200), 50, () => {
|
||||||
throw new RangeError('cake');
|
throw new RangeError('cake');
|
||||||
}), RangeError);
|
}), {instanceOf: RangeError});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('calls `.cancel()` on promise when it exists', async t => {
|
test('calls `.cancel()` on promise when it exists', async t => {
|
||||||
|
@ -54,7 +54,7 @@ test('calls `.cancel()` on promise when it exists', async t => {
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
await t.throwsAsync(pTimeout(promise, 50), pTimeout.TimeoutError);
|
await t.throwsAsync(pTimeout(promise, 50), {instanceOf: TimeoutError});
|
||||||
t.true(promise.isCanceled);
|
t.true(promise.isCanceled);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue