npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

timeable-promise

v1.7.4

Published

Various asynchronous operations with timeout support.

Readme

Timeable Promise

Version Downloads Dependencies Style TypeScript Checks Coverage Vulnerabilities License

Collection of asynchronous utilities for managing concurrency, sequencing, and timing. Provides helpers for running tasks in parallel or sequential order, controlling execution with timeouts, and working with settled promise results.

Installation

yarn add timeable-promise || npm install --save timeable-promise

Importing

This package supports two styles of import:

  1. Named exports from the entry point:
import { chunk, ..., waitFor } from 'timeable-promise';
  1. Direct path imports for individual utilities:
import chunk from 'timeable-promise/chunk';

Use whichever style fits your project. Named exports are convenient when you need several utilities at once, while direct path imports can reduce bundle size if you only need one.

This package is written in TypeScript and provides type definitions out of the box. Your editor will offer autocomplete and type safety automatically.

For the full list of exports, refer to the API Call Graph.

API Call Graph

The diagram below shows how the exported utilities interact with each other:

graph LR

%% --- Subgraphs ---
subgraph Core
  append["📎 append"]
  outcome["🎯 outcome"]
  toNumber["🔢 toNumber"]
end

subgraph Concurrency
  concurrent["⚡ concurrent"]
  concurrents["⚡⚡ concurrents"]
  parallel["🔀 parallel"]
end

subgraph Sequencing
  consecutive["➡️ consecutive"]
  consecutives["➡️➡️ consecutives"]
  sequential["⏩ sequential"]
end

poll["⏱️ poll"]
sleep["💤 sleep"]
waitFor["⏳ waitFor"]
untilSettledOrTimedOut["⏰ untilSettledOrTimedOut"]

%% --- Links ---
chunk["📦 chunk"] --> toNumber
concurrent --> chunk

concurrents --> concurrent
concurrents --> append
concurrents --> toNumber
concurrents --> outcome

consecutive --> outcome
consecutive --> toNumber

consecutives --> append
consecutives --> consecutive
consecutives --> toNumber
consecutives --> outcome

parallel --> chunk
parallel --> concurrent
parallel --> concurrents
parallel --> toNumber
parallel --> outcome

sequential --> chunk
sequential --> consecutive
sequential --> consecutives
sequential --> toNumber
sequential --> outcome

waitFor --> untilSettledOrTimedOut

%% --- Styling with original fills + black text ---
classDef core fill:#f9f,stroke:#333,stroke-width:2px,color:#000;
classDef concurrency fill:#bbf,stroke:#333,stroke-width:2px,color:#000;
classDef sequencing fill:#bfb,stroke:#333,stroke-width:2px,color:#000;
classDef utility fill:#ffd,stroke:#333,stroke-width:2px,color:#000;

class append,outcome,toNumber core;
class concurrent,concurrents,parallel concurrency;
class consecutive,consecutives,sequential sequencing;
class poll,sleep,waitFor,untilSettledOrTimedOut,chunk utility;

Functions

append()

function append<T>(accumulator, array): T[];

Defined in: append.ts:21

Appends items from one array onto the end of another.

Type Parameters

| Type Parameter | Description | | ------ | ------ | | T | The element type of the array. |

Parameters

| Parameter | Type | Description | | ------ | ------ | ------ | | accumulator | T[] | The accumulator array. | | array | T[] | The array items that will be appended. |

Returns

T[]

The appended accumulator array.

Example

Basic append:

const appended = append<number>([1, 2], [3, 4]);
console.log(appended); // [1, 2, 3, 4]

chunk()

function chunk<T, U>(array, size): U;

Defined in: chunk.ts:26

Splits an array into chunks of a given size. The final chunk will contain the remaining elements.

Type Parameters

| Type Parameter | Default type | Description | | ------ | ------ | ------ | | T | - | The item type of the array. | | U extends T[] | T[][] | T[] | The result type, which can be either: - T[] when no chunking is applied (size is 0 or omitted). - T[][] when chunking is applied (size > 0). |

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | array | T[] | undefined | The original array. | | size | number | 0 | The chunk size (default = 0). |

Returns

U

A new array containing chunked subarrays, or the original array if size is 0.

Example

Chunk into pairs:

const chunked = chunk<number>([1, 2, 3, 4, 5], 2);
console.log(chunked); // [[1, 2], [3, 4], [5]]

concurrent()

function concurrent<T, U>(
   array, 
   executor, 
concurrency): Promise<Settled<U>[]>;

Defined in: concurrent.ts:52

Runs the executor concurrently across items in a single array. If a concurrency value is provided, items are grouped into chunks of that size and each chunk is processed in parallel. The output is always a settled results array, but the input shape differs: either individual items or grouped chunks.

Type Parameters

| Type Parameter | Default type | Description | | ------ | ------ | ------ | | T | - | The item type of the array. | | U | T | The result type returned by the executor. |

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | array | T[] | undefined | The array items to be processed by executor. | | executor | ItemExecutor<T, U> | undefined | Executor function applied to each chunk. | | concurrency | number | 0 | The maximum concurrent execution size (default = 0). |

Returns

Promise<Settled<U>[]>

A promise resolving to an array of settled results.

Examples

With concurrency (groups of size 2):

const concurrentSettled1 = await concurrent<number>([1, 2, 3, 4, 5], async (chunk) => {
  return chunk.map(x => x * 2);
}, 2);
console.log(concurrentSettled1);
// [
//   { status: 'fulfilled', value: [2, 4] },
//   { status: 'fulfilled', value: [6, 8] },
//   { status: 'fulfilled', value: [10] }
// ]

Without concurrency (each item processed individually):

const concurrentSettled2 = await concurrent<number>([1, 2, 3], async (value) => {
  return value * 2;
});
console.log(concurrentSettled2);
// [
//   { status: 'fulfilled', value: 2 },
//   { status: 'fulfilled', value: 4 },
//   { status: 'fulfilled', value: 6 }
// ]

concurrents()

function concurrents<T, U>(
   array, 
   executor, 
concurrency): Promise<Settled<U>[]>;

Defined in: concurrents.ts:55

Runs the executor concurrently across multiple groups of an array. Internally calls concurrent for each group, then appends the results together. While the output format looks similar to concurrent, the orchestration differs: concurrents manages multiple concurrent runs, whereas concurrent handles a single run.

Type Parameters

| Type Parameter | Default type | Description | | ------ | ------ | ------ | | T | - | The item type of the array. | | U | T | The result type returned by the executor. |

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | array | T[] | undefined | The array groups to be processed by executor. | | executor | ItemExecutor<T, U> | undefined | Executor function applied to each group. | | concurrency | number | 0 | The maximum concurrent group size (default = 0). |

Returns

Promise<Settled<U>[]>

A promise resolving to an array of settled results.

Examples

With concurrency (groups of size 2):

const concurrentsSettled1 = await concurrents<number>([1, 2, 3, 4, 5], async (group) => {
  return group.map(x => x * 2);
}, 2);
console.log(concurrentsSettled1);
// [
//   { status: 'fulfilled', value: [2, 4] },
//   { status: 'fulfilled', value: [6, 8] },
//   { status: 'fulfilled', value: [10] }
// ]

Without concurrency (each item treated as its own group):

const concurrentsSettled2 = await concurrents<number>([1, 2, 3], async (value) => {
  return value * 2;
});
console.log(concurrentsSettled2);
// [
//   { status: 'fulfilled', value: 2 },
//   { status: 'fulfilled', value: 4 },
//   { status: 'fulfilled', value: 6 }
// ]

consecutive()

function consecutive<T, U>(
   array, 
   executor, 
concurrency): Promise<Settled<U>[]>;

Defined in: consecutive.ts:52

Runs the executor sequentially across items in a single array. If a concurrency value is provided, items are grouped into chunks of that size and each group is processed one after another. While the output is always a settled results array, the input shape differs: either individual items or grouped chunks.

Type Parameters

| Type Parameter | Default type | Description | | ------ | ------ | ------ | | T | - | The item type of the array. | | U | T | The result type returned by the executor. |

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | array | T[] | undefined | The array items to be processed by executor. | | executor | ItemExecutor<T, U> | undefined | Executor function applied to each item or group. | | concurrency | number | 0 | The maximum group size (default = 0). |

Returns

Promise<Settled<U>[]>

A promise resolving to an array of settled results.

Examples

With concurrency (groups of size 2):

const consecutiveSettled1 = await consecutive<number>([1, 2, 3, 4, 5], async (group) => {
  return group.map(x => x * 2);
}, 2);
console.log(consecutiveSettled1);
// [
//   { status: 'fulfilled', value: [2, 4] },
//   { status: 'fulfilled', value: [6, 8] },
//   { status: 'fulfilled', value: [10] }
// ]

Without concurrency (each item processed one by one):

const consecutiveSettled2 = await consecutive<number>([1, 2, 3], async (value) => {
  return value * 2;
});
console.log(consecutiveSettled2);
// [
//   { status: 'fulfilled', value: 2 },
//   { status: 'fulfilled', value: 4 },
//   { status: 'fulfilled', value: 6 }
// ]

consecutives()

function consecutives<T, U>(
   array, 
   executor, 
concurrency): Promise<Settled<U>[]>;

Defined in: consecutives.ts:53

Runs the executor sequentially across multiple groups of an array. Internally calls consecutive for each group, then appends the results together. This means the output looks similar to consecutive, but the orchestration differs: consecutives manages multiple consecutive runs, while consecutive handles a single run.

Type Parameters

| Type Parameter | Default type | Description | | ------ | ------ | ------ | | T | - | The item type of the array. | | U | T | The result type returned by the executor. |

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | array | T[] | undefined | The array groups to be processed by executor. | | executor | ItemExecutor<T, U> | undefined | Executor function applied to each group or item. | | concurrency | number | 0 | The maximum group size (default = 0). |

Returns

Promise<Settled<U>[]>

A promise resolving to an array of settled results.

Examples

With concurrency (groups of size 2):

const consecutivesSettled1 = await consecutives<number>([1, 2, 3, 4, 5], async (group) => {
  return group.map(x => x * 2);
}, 2);
console.log(consecutivesSettled1);
// [
//   { status: 'fulfilled', value: [2, 4] },
//   { status: 'fulfilled', value: [6, 8] },
//   { status: 'fulfilled', value: [10] }
// ]

Without concurrency (each item treated as its own group):

const consecutivesSettled2 = await consecutives<number>([1, 2, 3], async (value) => {
  return value * 2;
});
console.log(consecutivesSettled2);
// [
//   { status: 'fulfilled', value: 2 },
//   { status: 'fulfilled', value: 4 },
//   { status: 'fulfilled', value: 6 }
// ]

outcome()

function outcome<T, U>(executor, ...args): Promise<Settled<U>>;

Defined in: outcome.ts:42

Executes an executor and returns a PromiseSettledResult-like outcome.

Type Parameters

| Type Parameter | Default type | Description | | ------ | ------ | ------ | | T | - | The item type of the array. | | U | T | The result type returned by the executor. |

Parameters

| Parameter | Type | Description | | ------ | ------ | ------ | | executor | ItemExecutor<T, U> | Function to execute. | | ...args | [T[], number, T[][], PromiseSettledResult<U>[]] | Arguments passed to the executor. |

Returns

Promise<Settled<U>>

A settled outcome object.

Examples

Fulfilled outcome:

const ok = await outcome<number>(async (x: number) => x * 2, 5);
console.log(ok); // { status: 'fulfilled', value: 10 }

Rejected outcome:

const err = await outcome(() => { throw new Error('fail'); });
console.log(err); // { reason: Error('fail'), status: 'rejected' }

parallel()

function parallel<T, U>(
   array, 
   executor, 
concurrency): Promise<Settled<U>[]>;

Defined in: parallel.ts:54

Provides parallel execution of an executor across array items. If a concurrency value is provided, items are grouped into chunks of that size and processed concurrently via concurrents. Otherwise, the entire array is processed concurrently via concurrent.

Type Parameters

| Type Parameter | Default type | Description | | ------ | ------ | ------ | | T | - | The item type of the array. | | U | T | The result type returned by the executor. |

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | array | T[] | undefined | The array that is being processed in parallel. | | executor | ItemExecutor<T, U> | undefined | Executor function applied to each item or group. | | concurrency | number | 0 | The maximum group size (default = 0). |

Returns

Promise<Settled<U>[]>

A promise resolving to an array of settled results.

Examples

With concurrency (groups of size 2):

const parallelSettled1 = await parallel<number>([1, 2, 3, 4, 5], async (group) => {
  return group.map(x => x * 2);
}, 2);
console.log(parallelSettled1);
// [
//   { status: 'fulfilled', value: [2, 4] },
//   { status: 'fulfilled', value: [6, 8] },
//   { status: 'fulfilled', value: [10] }
// ]

Without concurrency (all items processed concurrently):

const parallelSettled2 = await parallel<number>([1, 2, 3], async (value) => {
  return value * 2;
});
console.log(parallelSettled2);
// [
//   { status: 'fulfilled', value: 2 },
//   { status: 'fulfilled', value: 4 },
//   { status: 'fulfilled', value: 6 }
// ]

poll()

function poll(
   executor, 
   interval, 
   immediately): PollHandle;

Defined in: poll.ts:41

Provides polling support without congestion when the executor takes longer than the interval. The executor receives a stopped function to check if polling has been stopped.

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | executor | PollExecutor | undefined | Function invoked on each poll. Receives a stopped function. | | interval | number | 1000 | Delay interval in milliseconds (default = 1000). | | immediately | boolean | false | Whether to run executor immediately at the beginning (default = false). |

Returns

PollHandle

An object with a stop function to end polling.

Example

Basic polling with stop control:

const timer = poll((stopped) => {
  // Do something promising here...
  if (!stopped()) {
    // Do something when polling is not stopped...
  }
}, 100);

setTimeout(() => {
  // Simulate the end of polling.
  timer.stop();
}, 1000);

sequential()

function sequential<T, U>(
   array, 
   executor, 
concurrency): Promise<Settled<U>[]>;

Defined in: sequential.ts:54

Provides sequential execution of an executor across array items. If a concurrency value is provided, items are grouped into chunks of that size and processed sequentially via consecutives. Otherwise, the entire array is processed sequentially via consecutive.

Type Parameters

| Type Parameter | Default type | Description | | ------ | ------ | ------ | | T | - | The item type of the array. | | U | T | The result type returned by the executor. |

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | array | T[] | undefined | The array that is being processed sequentially. | | executor | ItemExecutor<T, U> | undefined | Executor function applied to each item or group. | | concurrency | number | 0 | The maximum group size (default = 0). |

Returns

Promise<Settled<U>[]>

A promise resolving to an array of settled results.

Examples

With concurrency (groups of size 2):

const sequentialSettled1 = await sequential<number>([1, 2, 3, 4, 5], async (group) => {
  return group.map(x => x * 2);
}, 2);
console.log(sequentialSettled1);
// [
//   { status: 'fulfilled', value: [2, 4] },
//   { status: 'fulfilled', value: [6, 8] },
//   { status: 'fulfilled', value: [10] }
// ]

Without concurrency (all items processed one by one):

const sequentialSettled2 = await sequential<number>([1, 2, 3], async (value) => {
  return value * 2;
});
console.log(sequentialSettled2);
// [
//   { status: 'fulfilled', value: 2 },
//   { status: 'fulfilled', value: 4 },
//   { status: 'fulfilled', value: 6 }
// ]

sleep()

function sleep(timeout): Promise<void>;

Defined in: sleep.ts:20

Suspends execution for the given timeout duration.

Parameters

| Parameter | Type | Description | | ------ | ------ | ------ | | timeout | number | Timeout in milliseconds. |

Returns

Promise<void>

A promise that resolves after the given timeout.

Example

Sleep for 1 second:

console.time('sleep');
await sleep(1000);
console.timeEnd('sleep');

toNumber()

function toNumber(value, defaultValue): number;

Defined in: toNumber.ts:30

Converts a value to a number. If conversion fails, returns the default value.

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | value | unknown | undefined | The value to convert. | | defaultValue | number | 0 | The fallback if conversion is invalid (default = 0). |

Returns

number

A numeric value.

Examples

Convert string to number:

console.log(toNumber('42'));        // 42

Fallback value when conversion fails:

console.log(toNumber('abc', 10));   // 10

Null input defaults to 0:

console.log(toNumber(null));        // 0

untilSettledOrTimedOut()

function untilSettledOrTimedOut<T>(
   promiseExecutor, 
   timeoutExecutor, 
timeout): Promise<T>;

Defined in: untilSettledOrTimedOut.ts:67

Provides timeout support for a Promise. The executor runs until either it settles or the timeout expires, in which case the timeoutExecutor is invoked.

Type Parameters

| Type Parameter | Description | | ------ | ------ | | T | The type of the resolved return value. |

Parameters

| Parameter | Type | Description | | ------ | ------ | ------ | | promiseExecutor | PromiseExecutor<T> | Executor function, receives resolve, reject, and a pending function. | | timeoutExecutor | TimeoutExecutor<T> | Function invoked if timeout occurs, receives resolve and reject. | | timeout | number | Timeout in milliseconds. |

Returns

Promise<T>

A promise resolving or rejecting with the executor or timeoutExecutor result.

Example

Executor with timeout fallback:

const executor = (resolve, reject, pending) => {
  // Do something promising here...
  if (pending()) {
    try {
      // Do something more promising here...
      resolve(true);
    } catch (ex) {
      reject(false);
    }
  }
};

const timeoutExecutor = (resolve, reject) => {
  try {
    resolve(true);
  } catch (ex) {
    reject(false);
  }
};

const timeout = 5000;
const response = await untilSettledOrTimedOut<boolean>(executor, timeoutExecutor, timeout)
  .catch(ex => console.log('nay :(', ex));
console.log(`resolved with ${response}, yay!`);

waitFor()

function waitFor(
   predicate, 
   timeout, 
interval): Promise<void>;

Defined in: waitFor.ts:34

Wait until a predicate returns true or timeout occurs.

Parameters

| Parameter | Type | Default value | Description | | ------ | ------ | ------ | ------ | | predicate | () => boolean | undefined | Function returning a boolean, checked repeatedly. | | timeout | number | undefined | Max time to wait in ms. | | interval | number | 1000 | Polling interval in ms (default = 1000). |

Returns

Promise<void>

A promise that resolves when predicate is true or timeout expires.

Example

Wait for predicate to become true:

let inflight = true;
const predicate = () => !inflight;
const timeout = 5000;

setTimeout(() => {
  inflight = false; // long process done
}, 1000);

console.time('waitFor');
await waitFor(predicate, timeout, 200);
console.timeEnd('waitFor');

Type Aliases

ItemExecutor()

type ItemExecutor<T, U> = (value, index, array, accumulator?) => Promise<U> | U;

Defined in: outcome.ts:8

Type Parameters

| Type Parameter | Default type | | ------ | ------ | | T | - | | U | T |

Parameters

| Parameter | Type | | ------ | ------ | | value | T[] | | index | number | | array | T[][] | | accumulator? | PromiseSettledResult<U>[] |

Returns

Promise<U> | U


PollExecutor()

type PollExecutor = (stopped) => Promise<void> | void;

Defined in: poll.ts:9

Parameters

| Parameter | Type | | ------ | ------ | | stopped | () => boolean |

Returns

Promise<void> | void


PollHandle

type PollHandle = {
  stop: () => void;
};

Defined in: poll.ts:11

Properties

| Property | Type | Defined in | | ------ | ------ | ------ | | stop | () => void | poll.ts:12 |


PromiseConstructor

type PromiseConstructor<T> = ConstructorParameters<typeof Promise>[0];

Defined in: untilSettledOrTimedOut.ts:8

Type Parameters

| Type Parameter | | ------ | | T |


PromiseExecutor()

type PromiseExecutor<T> = (resolve, reject, pending) => void;

Defined in: untilSettledOrTimedOut.ts:10

Type Parameters

| Type Parameter | | ------ | | T |

Parameters

| Parameter | Type | | ------ | ------ | | resolve | Parameters<PromiseConstructor<T>>[0] | | reject | Parameters<PromiseConstructor<T>>[1] | | pending | () => boolean |

Returns

void


Settled

type Settled<T> = PromiseSettledResult<T>;

Defined in: outcome.ts:19

Type Parameters

| Type Parameter | | ------ | | T |


TimeoutExecutor()

type TimeoutExecutor<T> = (resolve, reject) => void;

Defined in: untilSettledOrTimedOut.ts:19

Type Parameters

| Type Parameter | | ------ | | T |

Parameters

| Parameter | Type | | ------ | ------ | | resolve | Parameters<PromiseConstructor<T>>[0] | | reject | Parameters<PromiseConstructor<T>>[1] |

Returns

void

Development Dependencies

You will need to install Node.js as a local development dependency. The npm package manager comes bundled with all recent releases of Node.js. You can also use yarn as a package manager.

yarn or npm install will attempt to resolve any npm module dependencies that have been declared in the project's package.json file, installing them into the node_modules folder.

yarn || npm install

Run Leak, Lint, Performance, Type and Unit Tests

To make sure we did not break anything, let's run all the tests:

yarn test || npm run test

Run leak tests only:

yarn test:leak || npm run test:leak

Run linter only:

yarn test:lint || npm run test:lint

Run performance tests only:

yarn test:perf || npm run test:perf

Run type check only:

yarn test:type || npm run test:type

Run unit tests only:

yarn test:unit || npm run test:unit

Contributing

If you would like to contribute code to Timeable Promise repository you can do so through GitHub by forking the repository and sending a pull request.

If you do not agree to Contribution Agreement, do not contribute any code to Timeable Promise repository.

When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. Please also include appropriate test cases.

That's it! Thank you for your contribution!

License

Copyright (c) 2018-2025 Richard Huang.

This module is free software, licensed under: GNU Affero General Public License (AGPL-3.0).

Documentation and other similar content are provided under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.