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

@superutils/promise

v1.0.6

Published

An extended Promise with extra features such as status tracking, deferred/throttled execution, timeout and retry mechanism.

Readme

@superutils/promise

An extended Promise implementation, named PromisE, that provides additional features and utilities for easier asynchronous flow control in JavaScript and TypeScript applications.

This package offers a drop-in replacement for the native Promise that includes status tracking (.pending, .resolved, .rejected) and a suite of powerful static methods for common asynchronous patterns like deferred execution, throttling, and cancellable fetches.

For full API reference check out the docs page.

Table of Contents

Features

  • Promise Status: Easily check if a promise is pending, resolved, or rejected.
  • Deferred Execution: Defer or throttle promise-based function calls with PromisE.deferred().
  • Auto-cancellable Fetch: Automatically abort pending requests when subsequent requests are made using PromisE.deferredFetch() and PromisE.deferredPost().
  • Auto-cancellable Fetch: The PromisE.deferredFetch and PromisE.deferredPost utilities automatically abort pending requests when a new deferred/throttled call is made.
  • Timeouts: Wrap any promise with a timeout using PromisE.timeout().
  • Rich Utilities: A collection of static methods like .all(), .race(), .delay(), and more, all returning PromisE instances.

Installation

npm install @superutils/core @superutils/promise

Usage

new PromisE(executor): Drop-in replacement for Promise

The PromisE class can be used just like the native Promise. The key difference is the addition of status properties:

import { PromisE } from '@superutils/promise'

const p = new PromisE(resolve => setTimeout(() => resolve('done'), 1000))

console.log(p.pending) // true

p.then(result => {
	console.log(result) // 'done'
	console.log(p.resolved) // true
	console.log(p.pending) // false
})

and the ability to early finalize a promise:

import { PromisE } from '@superutils/promise'
const p = new PromisE(resolve => setTimeout(() => resolve('done'), 10000))
p.then(result => console.log(result))
// resolve the promise early
setTimeout(() => p.resolve('finished early'), 500)

PromisE.try(fn): Static methods

Drop-in replacement for all Promise static methods such as .all(), .race(), .reject, .resolve, .try(), .withResolvers()....

import { PromisE } from '@superutils/promise'

const p = PromisE.try(() => {
	throw new Error('Something went wrong')
})

p.catch(error => {
	console.error(error.message) // 'Something went wrong'
	console.log(p.rejected) // true
})

new PromisE(promise)

Check status of an existing promise.

import { PromisE } from '@superutils/promise'
const x = Promise.resolve(1)
const p = new PromisE(x)
console.log(p.pending) // false
console.log(p.resolved) // true
console.log(p.rejected) // false

PromisE.delay(duration): Async delay

Creates a promise that resolves after a specified duration, essentially a promise-based setTimeout.

import PromisE from '@superutils/promise'
// Wait until `appReady` becomes truthy but
while (!appReady) {
	await PromisE.delay(100)
}

PromisE.delay(duration, callback): execute after delay

Creates a promise that executes a function after a specified duration and returns the value the function returns.

If callback returns undefined, default value will be the duration.

import PromisE from '@superutils/promise'

const callback = () => {
	/* do stuff here */
}
await PromisE.delay(100, callback)

PromisE.deferred(options): async debounced/throttled execution

Create a function that debounces or throttles promise-returning function calls. This is useful for scenarios like auto-saving user input or preventing multiple rapid API calls.

import PromisE, { ResolveIgnored } from '@superutils/promise'

// Create a deferred function that waits 300ms after the last call
const deferredSave = PromisE.deferred({
	defer: 300,
	/** ignored promises will resolve with `undefined` */
	resolveIgnored: ResolveIgnored.WITH_UNDEFINED,

	/** ignored promises will NEVER be resolved/rejected
	 * USE WITH CAUTION!
	 */
	resolveIgnored: ResolveIgnored.NEVER,

	// ignored promises will resolve with the result of the last call
	resolveIgnored: ResolveIgnored.WITH_LAST, // (default)
})

// Simulate rapid calls
deferredSave(() => api.save({ text: 'first' }))
deferredSave(() => api.save({ text: 'second' }))
// Only the 3rd call is executed.
// But all of them are resolved with the result of the 3rd call when `resolveIgnored` is `ResolveIgnored.WITH_LAST`
deferredSave(() => api.save({ text: 'third' })).then(response =>
	console.log('Saved!', response),
)

PromisE.deferredCallback(callback, options): async debounced/throttled callbacks

Same as PromisE.deferred but for event handlers etc.

import PromisE from '@superutils/promise'

// Input change handler
const handleChange = (e: { target: { value: number } }) =>
	console.log(e.target.value)
// Change handler with `PromisE.deferred()`
const handleChangeDeferred = PromisE.deferredCallback(handleChange, {
	delayMs: 300,
	throttle: false,
})
// Simulate input change events after prespecified delays
const delays = [100, 150, 200, 550, 580, 600, 1000, 1100]
delays.forEach(timeout =>
	setTimeout(
		() => handleChangeDeferred({ target: { value: timeout } }),
		timeout,
	),
)
// Prints:
// 200, 600, 1100

PromisE.timeout(duration, ...promises): Reject after timeout

Reject stuck or unexpectedly lenghthy promise(s) after a specified timeout:

import { PromisE } from '@superutils/promise'

PromisE.timeout(
	5000, // timeout after 5000ms
	api.save({ text: 'takes longer than 5s to finish' }),
).catch(console.log)
// Error: Error('Timed out after 5000ms')

Show a message when loading is too long:

import { PromisE } from '@superutils/promise'

const loadUserNProducts = () => {
	const promise = PromisE.timeout(
		5000, // timeout after 5000ms
		api.getUser(),
		api.getProducts(),
	)
	const [user, products] = await promise.catch(err => {
		// promise did not time out, but was rejected
		// because one of the data promises rejected
		if (!promise.timedout) return Promise.reject(err)

		// promise timed out >> print/update UI
		console.log('Request is taking longer than expected......')
		// now return the "data promise", the promise(s) provided in the PromisE.timeout()
		// If more than one promises provided, then `promise.data` will be the combination of them all: `PromisE.all(...promises)`
		return promise.data
	})
	return [user, products]
}
loadUserNProducts()