pax_global_header00006660000000000000000000000064135002402560014507gustar00rootroot0000000000000052 comment=1fa312b57450a6d8d39d52ac55f476109474bfe3 delay-4.3.0/000077500000000000000000000000001350024025600126115ustar00rootroot00000000000000delay-4.3.0/.editorconfig000066400000000000000000000002571350024025600152720ustar00rootroot00000000000000root = true [*] indent_style = tab end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.yml] indent_style = space indent_size = 2 delay-4.3.0/.gitattributes000066400000000000000000000000231350024025600154770ustar00rootroot00000000000000* text=auto eol=lf delay-4.3.0/.github/000077500000000000000000000000001350024025600141515ustar00rootroot00000000000000delay-4.3.0/.github/funding.yml000066400000000000000000000001331350024025600163230ustar00rootroot00000000000000github: sindresorhus open_collective: sindresorhus custom: https://sindresorhus.com/donate delay-4.3.0/.gitignore000066400000000000000000000000271350024025600146000ustar00rootroot00000000000000node_modules yarn.lock delay-4.3.0/.npmrc000066400000000000000000000000231350024025600137240ustar00rootroot00000000000000package-lock=false delay-4.3.0/.travis.yml000066400000000000000000000000641350024025600147220ustar00rootroot00000000000000language: node_js node_js: - '10' - '8' - '6' delay-4.3.0/index.d.ts000066400000000000000000000041321350024025600145120ustar00rootroot00000000000000declare namespace delay { interface ClearablePromise extends Promise { /** Clears the delay and settles the promise. */ clear(): void; } /** Minimal subset of `AbortSignal` that delay will use if passed. This avoids a dependency on dom.d.ts. The dom.d.ts `AbortSignal` is compatible with this one. */ interface AbortSignal { readonly aborted: boolean; addEventListener( type: 'abort', listener: () => void, options?: {once?: boolean} ): void; removeEventListener(type: 'abort', listener: () => void): void; } interface Options { /** An optional AbortSignal to abort the delay. If aborted, the Promise will be rejected with an AbortError. */ signal?: AbortSignal; } } type Delay = { /** Create a promise which resolves after the specified `milliseconds`. @param milliseconds - Milliseconds to delay the promise. @returns A promise which resolves after the specified `milliseconds`. */ (milliseconds: number, options?: delay.Options): delay.ClearablePromise; /** Create a promise which resolves after the specified `milliseconds`. @param milliseconds - Milliseconds to delay the promise. @returns A promise which resolves after the specified `milliseconds`. */ ( milliseconds: number, options?: delay.Options & { /** Value to resolve in the returned promise. */ value: T; } ): delay.ClearablePromise; /** Create a promise which rejects after the specified `milliseconds`. @param milliseconds - Milliseconds to delay the promise. @returns A promise which rejects after the specified `milliseconds`. */ // TODO: Allow providing value type after https://github.com/Microsoft/TypeScript/issues/5413 will be resolved. reject( milliseconds: number, options?: delay.Options & { /** Value to reject in the returned promise. */ value?: unknown; } ): delay.ClearablePromise; }; declare const delay: Delay & { createWithTimers(timers: { clearTimeout: typeof clearTimeout; setTimeout: typeof setTimeout; }): Delay; // TODO: Remove this for the next major release default: typeof delay; }; export = delay; delay-4.3.0/index.js000066400000000000000000000027501350024025600142620ustar00rootroot00000000000000'use strict'; const createAbortError = () => { const error = new Error('Delay aborted'); error.name = 'AbortError'; return error; }; const createDelay = ({clearTimeout: defaultClear, setTimeout: set, willResolve}) => (ms, {value, signal} = {}) => { if (signal && signal.aborted) { return Promise.reject(createAbortError()); } let timeoutId; let settle; let rejectFn; const clear = defaultClear || clearTimeout; const signalListener = () => { clear(timeoutId); rejectFn(createAbortError()); }; const cleanup = () => { if (signal) { signal.removeEventListener('abort', signalListener); } }; const delayPromise = new Promise((resolve, reject) => { settle = () => { cleanup(); if (willResolve) { resolve(value); } else { reject(value); } }; rejectFn = reject; timeoutId = (set || setTimeout)(settle, ms); }); if (signal) { signal.addEventListener('abort', signalListener, {once: true}); } delayPromise.clear = () => { clear(timeoutId); timeoutId = null; cleanup(); settle(); }; return delayPromise; }; const delay = createDelay({willResolve: true}); delay.reject = createDelay({willResolve: false}); delay.createWithTimers = ({clearTimeout, setTimeout}) => { const delay = createDelay({clearTimeout, setTimeout, willResolve: true}); delay.reject = createDelay({clearTimeout, setTimeout, willResolve: false}); return delay; }; module.exports = delay; // TODO: Remove this for the next major release module.exports.default = delay; delay-4.3.0/index.test-d.ts000066400000000000000000000016771350024025600155020ustar00rootroot00000000000000/// import {expectType} from 'tsd'; import delay = require('.'); import {ClearablePromise} from '.'; expectType>(delay(200)); expectType>(delay(200, {value: 'πŸ¦„'})); expectType>(delay(200, {value: 0})); expectType>( delay(200, {signal: new AbortController().signal}) ); expectType>(delay.reject(200, {value: 'πŸ¦„'})); expectType>(delay.reject(200, {value: 0})); const customDelay = delay.createWithTimers({clearTimeout, setTimeout}); expectType>(customDelay(200)); expectType>(customDelay(200, {value: 'πŸ¦„'})); expectType>(customDelay(200, {value: 0})); expectType>(customDelay.reject(200, {value: 'πŸ¦„'})); expectType>(customDelay.reject(200, {value: 0})); delay-4.3.0/license000066400000000000000000000021251350024025600141560ustar00rootroot00000000000000MIT License Copyright (c) Sindre Sorhus (sindresorhus.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. delay-4.3.0/package.json000066400000000000000000000014521350024025600151010ustar00rootroot00000000000000{ "name": "delay", "version": "4.3.0", "description": "Delay a promise a specified amount of time", "license": "MIT", "repository": "sindresorhus/delay", "author": { "name": "Sindre Sorhus", "email": "sindresorhus@gmail.com", "url": "sindresorhus.com" }, "engines": { "node": ">=6" }, "scripts": { "test": "xo && ava && tsd" }, "files": [ "index.js", "index.d.ts" ], "keywords": [ "promise", "resolve", "delay", "defer", "wait", "stall", "timeout", "settimeout", "event", "loop", "next", "tick", "delay", "async", "await", "promises", "bluebird" ], "devDependencies": { "abort-controller": "^3.0.0", "ava": "1.4.1", "currently-unhandled": "^0.4.1", "in-range": "^1.0.0", "time-span": "^3.0.0", "tsd": "^0.7.1", "xo": "^0.24.0" } } delay-4.3.0/readme.md000066400000000000000000000072061350024025600143750ustar00rootroot00000000000000# delay [![Build Status](https://travis-ci.org/sindresorhus/delay.svg?branch=master)](https://travis-ci.org/sindresorhus/delay) > Delay a promise a specified amount of time ## Install ``` $ npm install delay ``` ## Usage ```js const delay = require('delay'); (async () => { bar(); await delay(100); // Executed 100 milliseconds later baz(); })(); ``` ## API ### delay(milliseconds, [options]) Create a promise which resolves after the specified `milliseconds`. ### delay.reject(milliseconds, [options]) Create a promise which rejects after the specified `milliseconds`. #### milliseconds Type: `number` Milliseconds to delay the promise. #### options Type: `Object` ##### value Type: `any` Optional value to resolve or reject in the returned promise. ##### signal Type: [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) The returned promise will be rejected with an AbortError if the signal is aborted. AbortSignal is available in all modern browsers and there is a [ponyfill for Node.js](https://github.com/mysticatea/abort-controller). ### delayPromise.clear() Clears the delay and settles the promise. ### delay.createWithTimers({clearTimeout, setTimeout}) Creates a new `delay` instance using the provided functions for clearing and setting timeouts. Useful if you're about to stub timers globally, but you still want to use `delay` to manage your tests. ## Advanced usage Passing a value: ```js const delay = require('delay'); (async() => { const result = await delay(100, {value: 'πŸ¦„'}); // Executed after 100 milliseconds console.log(result); //=> 'πŸ¦„' })(); ``` Using `delay.reject()`, which optionally accepts a value and rejects it `ms` later: ```js const delay = require('delay'); (async () => { try { await delay.reject(100, {value: new Error('πŸ¦„')}); console.log('This is never executed'); } catch (error) { // 100 milliseconds later console.log(error); //=> [Error: πŸ¦„] } })(); ``` You can settle the delay early by calling `.clear()`: ```js const delay = require('delay'); (async () => { const delayedPromise = delay(1000, {value: 'Done'}); setTimeout(() => { delayedPromise.clear(); }, 500); // 500 milliseconds later console.log(await delayedPromise); //=> 'Done' })(); ``` You can abort the delay with an AbortSignal: ```js const delay = require('delay'); (async () => { const abortController = new AbortController(); setTimeout(() => { abortController.abort(); }, 500); try { await delay(1000, {signal: abortController.signal}); } catch (error) { // 500 milliseconds later console.log(error.name) //=> 'AbortError' } })(); ``` Create a new instance that is unaffected by libraries such as [lolex](https://github.com/sinonjs/lolex/): ```js const delay = require('delay'); const customDelay = delay.createWithTimers({clearTimeout, setTimeout}); (async() => { const result = await customDelay(100, {value: 'πŸ¦„'}); // Executed after 100 milliseconds console.log(result); //=> 'πŸ¦„' })(); ``` ## Related - [delay-cli](https://github.com/sindresorhus/delay-cli) - CLI for this module - [p-cancelable](https://github.com/sindresorhus/p-cancelable) - Create a promise that can be canceled - [p-min-delay](https://github.com/sindresorhus/p-min-delay) - Delay a promise a minimum amount of time - [p-immediate](https://github.com/sindresorhus/p-immediate) - Returns a promise resolved in the next event loop - think `setImmediate()` - [p-timeout](https://github.com/sindresorhus/p-timeout) - Timeout a promise after a specified amount of time - [More…](https://github.com/sindresorhus/promise-fun) ## License MIT Β© [Sindre Sorhus](https://sindresorhus.com) delay-4.3.0/test.js000066400000000000000000000077041350024025600141360ustar00rootroot00000000000000import {serial as test} from 'ava'; import timeSpan from 'time-span'; import inRange from 'in-range'; import currentlyUnhandled from 'currently-unhandled'; import {AbortController} from 'abort-controller'; import m from '.'; const getCurrentlyUnhandled = currentlyUnhandled(); test('returns a resolved promise', async t => { const end = timeSpan(); await m(50); t.true(inRange(end(), 30, 70), 'is delayed'); }); test('returns a rejected promise', async t => { const end = timeSpan(); await t.throwsAsync( m.reject(50, {value: new Error('foo')}), 'foo' ); t.true(inRange(end(), 30, 70), 'is delayed'); }); test('able to resolve a falsy value', async t => { t.is( await m(50, {value: 0}), 0 ); }); test('able to reject a falsy value', async t => { t.plan(1); try { await m.reject(50, {value: false}); } catch (error) { t.is(error, false); } }); test('delay defaults to 0 ms', async t => { const end = timeSpan(); await m(); t.true(end() < 30); }); test('reject will cause an unhandledRejection if not caught', async t => { const reason = new Error('foo'); const promise = m.reject(0, {value: reason}); await m(10); t.deepEqual(getCurrentlyUnhandled(), [{ reason, promise }], 'Promise should be unhandled'); promise.catch(() => {}); await m(10); t.deepEqual(getCurrentlyUnhandled(), [], 'no unhandled rejections now'); }); test('can clear a delayed resolution', async t => { const end = timeSpan(); const delayPromise = m(1000, {value: 'success!'}); delayPromise.clear(); const success = await delayPromise; t.true(end() < 30); t.is(success, 'success!'); }); test('can clear a delayed rejection', async t => { const end = timeSpan(); const delayPromise = m.reject(1000, {value: new Error('error!')}); delayPromise.clear(); await t.throwsAsync(delayPromise, /error!/); t.true(end() < 30); }); test('resolution can be aborted with an AbortSignal', async t => { const end = timeSpan(); const abortController = new AbortController(); setTimeout(() => abortController.abort(), 1); await t.throwsAsync( m(1000, {signal: abortController.signal}), {name: 'AbortError'} ); t.true(end() < 30); }); test('resolution can be aborted with an AbortSignal if a value is passed', async t => { const end = timeSpan(); const abortController = new AbortController(); setTimeout(() => abortController.abort(), 1); await t.throwsAsync( m(1000, {value: 123, signal: abortController.signal}), {name: 'AbortError'} ); t.true(end() < 30); }); test('rejection can be aborted with an AbortSignal if a value is passed', async t => { const end = timeSpan(); const abortController = new AbortController(); setTimeout(() => abortController.abort(), 1); await t.throwsAsync( m.reject(1000, {value: new Error(), signal: abortController.signal}), {name: 'AbortError'} ); t.true(end() < 30); }); test('rejects with AbortError if AbortSignal is already aborted', async t => { const end = timeSpan(); const abortController = new AbortController(); abortController.abort(); await t.throwsAsync( m(1000, {signal: abortController.signal}), {name: 'AbortError'} ); t.true(end() < 30); }); test('can create a new instance with fixed timeout methods', async t => { const cleared = []; const callbacks = []; const custom = m.createWithTimers({ clearTimeout(handle) { cleared.push(handle); }, setTimeout(callback, ms) { const handle = Symbol('handle'); callbacks.push({callback, handle, ms}); return handle; } }); const first = custom(50, {value: 'first'}); t.is(callbacks.length, 1); t.is(callbacks[0].ms, 50); callbacks[0].callback(); t.is(await first, 'first'); const second = custom.reject(40, {value: 'second'}); t.is(callbacks.length, 2); t.is(callbacks[1].ms, 40); callbacks[1].callback(); try { await second; } catch (error) { t.is(error, 'second'); } const third = custom(60); t.is(callbacks.length, 3); t.is(callbacks[2].ms, 60); third.clear(); t.is(cleared.length, 1); t.is(cleared[0], callbacks[2].handle); });