GithubHelp home page GithubHelp logo

delay's Introduction

delay

Delay a promise a specified amount of time

If you target Node.js only, you can use import {setTimeout} from 'node:timers/promises'; await setTimeout(1000); instead. This package can still be useful if you need browser support or the extra features.

Install

npm install delay

Usage

import delay from 'delay';

bar();

await delay(100);

// Executed 100 milliseconds later
baz();

API

delay(milliseconds, options?) default import

Create a promise which resolves after the specified milliseconds.

rangeDelay(minimum, maximum, options?)

Create a promise which resolves after a random amount of milliseconds between minimum and maximum has passed.

Useful for tests and web scraping since they can have unpredictable performance. For example, if you have a test that asserts a method should not take longer than a certain amount of time, and then run it on a CI, it could take longer. So with this method, you could give it a threshold instead.

milliseconds

mininum

maximum

Type: number

Milliseconds to delay the promise.

options

Type: object

value

Type: unknown

A value to resolve in the returned promise.

import delay from 'delay';

const result = await delay(100, {value: 'πŸ¦„'});

// Executed after 100 milliseconds
console.log(result);
//=> 'πŸ¦„'
signal

Type: AbortSignal

The returned promise will be rejected with an AbortError if the signal is aborted.

import delay from 'delay';

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'
}

clearDelay(delayPromise)

Clears the delay and settles the promise.

If you pass in a promise that is already cleared or a promise coming from somewhere else, it does nothing.

import delay, {clearDelay} from 'delay';

const delayedPromise = delay(1000, {value: 'Done'});

setTimeout(() => {
	clearDelay(delayedPromise);
}, 500);

// 500 milliseconds later
console.log(await delayedPromise);
//=> 'Done'

createDelay({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.

import {createDelay} from 'delay';

const customDelay = createDelay({clearTimeout, setTimeout});

const result = await customDelay(100, {value: 'πŸ¦„'});

// Executed after 100 milliseconds
console.log(result);
//=> 'πŸ¦„'

Related

delay's People

Contributors

ariporad avatar bendingbender avatar bfred-it avatar dex4er avatar dmitry-korolev avatar felixfbecker avatar jamestalmage avatar novemberborn avatar ntwb avatar olsonpm avatar richienb avatar samverschueren avatar sindresorhus avatar timdp avatar torgen avatar yuler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

delay's Issues

.then(delay(ms)) no longer working again

Same issue as #1, brought back by commit 90d16f2

I will create a PR assuming you still want this functionality. Honestly I only looked at the code base after reading delay(ms) behaves differently from .then(delay(ms)) in the docs. Personally I would prefer to have delay(ms) return a promise always, and to allow users to wrap it if needed e.g. .then(res => delay(ms, res)).

Your library though :)

administrating timeoutId

the timeoutId null-check in the clear() function caught me off guard a little bit. First of all, it's strictly unnecessary since everything done in there is idempotent, so

delayPromise.clear = () => {
	if (timeoutId) {
		clearTimeout(timeoutId);
		timeoutId = null;
		settle(value);
	}
};

really is equivalent to

delayPromise.clear = () => {
	clearTimeout(timeoutId);
	settle(value);
};

However, if keeping track of the 'settled' state is important, then we should also alter the promise definition to

const delayPromise = new Promise((resolve, reject) => {
	settle = willResolve ? resolve : reject;
	timeoutId = setTimeout(() => {
		timeoutId = null;
		settle(value);
	}, ms);
});

In which case we could add

delayPromise.hasSettled = () => !timeoutId;

to interrogate the delay as to its status.

All existing tests pass either way, so it doesn't really matter, but it seems a bit strange to have a null check that doesn't even do its (largely irrelevant) job if the delayPromise has already settled through timer completion.

btw, I really like the 3.0 changes. great module

Allow to change the promise result when calling clear

It would be nice to add a non mandatory parameter to clear(), to change the result of the delay() promise.

The main purpose would be to allow the code running after a delay() to behave differently if the delay was cleared (like doing nothing, if the user want to cancel the scheduled work).

As clear doesn't accept any parameter, the change would be backward compatible.

Support waiting until date

It would be useful if delay allowed waiting until a specific date. This is useful for timers, schedulers and cron jobs.

const delay = require('delay');

await delay.date(date)

// @sindresorhus

(BUG) SINON <> DELAY - Bug when using Sinon 'useFakeTimers' and Delay

When using Sinon in my project to test my application, I realized that the test never stopped running and after some time I ended up discovering this "incompatibility".

Here is an example code to reproduce the problem:

const sinon = require('sinon'); // 9.0.2
const delay = require('delay'); // 4.3.0

async function run() {
  sinon.useFakeTimers(1590721200000);
  await delay(1000);
  console.log('This message will never be executed !!!');
}
run();

Type definition for `createWithTimers` makes it hard to use

setTimeout in Node.js now has stuff like __promisify__ attached to it. The type definition should be adjusted so that you can do stuff like this:

const unrefDelay = delay.createWithTimers({
  clearTimeout,
  setTimeout (...args) {
    return setTimeout(...args).unref()
  },
})

See this line:

setTimeout: typeof setTimeout;

Slight (breaking) change to the API

Since this thing is only 9 hours old, I think we're safe doing it.

When used in this fashion:

promiseFn()
  .then(delay(200))

I think it should delay 200ms from the time the first promise resolves.

Cancelation?

I know there's currently a whole debate about cancelable promises and such, but at any rate, there's currently no way to clear the timeout that delay sets. Has the possibility of introducing a cancelation function for this been considered yet?

Factory method to create delay implementation with bound timer methods

It'd be useful if I could do the following:

import { factory } from 'delay'

const delay = factory({ setTimeout, clearTimeout })

Since this binds the implementation to the timer methods I've provided, I can then safely stub the timers using say lolex and still use the delay interface.

Typescript dom reference causes failure in non-DOM contexts

The lib reference to dom

/// <reference lib="dom"/>
prevents this from being properly usable within non-DOM contexts such as react-native.

node_modules/typescript/lib/lib.dom.d.ts:17604:6 - error TS2300: Duplicate identifier 'RequestInfo'.

17604 type RequestInfo = Request | string;
           ~~~~~~~~~~~

node_modules/@types/react-native/globals.d.ts:92:14
92 declare type RequestInfo = Request | string;
                ~~~~~~~~~~~
RequestInfo' was also declared here.

Delaying for more than ~24.8 days causes TimeoutOverflowWarning and immediate promise resolution

The default implementation of setTimeout can only accept values within the range of positive signed 32-bit integers. Passing a timeout greater than (2^31)-1 milliseconds (0x7FFFFFFF) yields a TimeoutOverflowWarning and causes the runtime to ignore the specified timeout, assuming a value of 1ms (which by the way seems a dangerous default, I would have opted for using the maximum supported value or straight out throw an error).

This unexpected behavior is not documented in the README, but rather than documenting this quirk of the runtime I'd like to propose a solution: instead of relying on the bare setTimeout, delay could use a wrapped version of it. Something like this:

const maxSupportedTimeout = 0x7fffffff;
type TimeoutContext = { id: ReturnType<typeof setTimeout> };
const defaultSetTimeout = (
  callback: (...args: any[]) => void,
  ms: number,
  timeoutContext?: Partial<TimeoutContext>
): TimeoutContext => {
  timeoutContext = timeoutContext || { id: undefined };
  if (ms > maxSupportedTimeout) {
    timeoutContext.id = setTimeout(
      defaultSetTimeout,
      maxSupportedTimeout,
      callback,
      ms - maxSupportedTimeout,
      timeoutContext
    );
  } else {
    timeoutContext.id = setTimeout(callback, ms);
  }
  return timeoutContext as TimeoutContext;
};
const defaultClearTimeout = (timeoutContext: TimeoutContext) =>
  clearTimeout(timeoutContext.id);

The timeoutContext is passed by reference, therefore each time defaultSetTimeout gets called the timeout id gets updated, so that defaultClearTimeout can always access the most recent value.

Problems using

I've been using the delay module in a typescript module (@google-cloud/profiler).

I'd previously used the type definitions from DefinitelyTyped, so @types/delay, without issue. But when I try to use version 3.1.0 of this module (and use the types from this latest version), my module no longer compiles, and I get errors like:

ts/test/test-time-profiler.ts:65:16 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof import("/usr/local/google/home/nolanmar/cloud-profiler-nodejs-working/cloud-profiler-nodejs/node_modules/delay/index")' has no compatible call signatures.

65          await delay(2 * durationMillis);
                  ~~~~~~~~~~~~~~~~~~~~~~~~~

Is this expected? Any advice for how I can migrate to version 3.1.0 of `delay?

Mistaken in type definition? TypeScript compiler refuses to allow calling default import

Not sure how to express what is happening exactly, and perhaps it is related to (#32), but tsc won't compile the following code:

// code.ts
import * as delay from 'delay';
delay(100);
code.ts:3:1 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof import("/home/user/my-project/node_modules/delay/index")' has no compatible call signatures.

3 delay(100);
  ~~~~~~~~~~


Found 1 error.

However, it seems that I can "fool" tsc into compiling it anyway by doing this:

import * as delayDefault from 'delay';
const delay: any = delayDefault;
delay(100);

I am using node 10.15.1, delay 4.1.0, tsc 3.3.1, and Linux (4.9.0-8-amd64)

How can i stub it in tests?

When I use the library how can I fake the delay and instead of waiting return an instantly resolving Promise?

Unexpected token: name (CancelError)

With production settings, uglify gives me this error, which points at delay:

Message: Unexpected token: name (CancelError)
File: /dist/ssr.js
Line number: 1516
Column number: 6
Source error:

Line 1516: class CancelError extends Error {
----------------^
Line 1517:     constructor(message) {

The comment by @yudao in this thread lead me here, I assume it's the same problem: brunch/brunch#1715

Is this because Uglify can't speak ES6 yet?

If so, I'll try one of these when I have time:

bablified distributable

This dependency currently crashes webpacks uglify if exclude "node_modules" is given, which most projects still seem to do. It would be nice if it had a bablified distributable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.