@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.
Table of Contents
- Features
- Installation
- Usage
new PromisE(executor): Drop-in replacement forPromisenew PromisE(promise): Check promise statusPromisE.try(): Static methodsPromisE.delay(): Async delayPromisE.deferred(): Async debounced/throttled callbackPromisE.timeout(): Reject after timeout
Features
- Promise Status: Easily check if a promise is
pending,resolved, orrejected. - 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()andPromisE.deferredPost(). - Auto-cancellable Fetch: The
PromisE.deferredFetchandPromisE.deferredPostutilities 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 returningPromisEinstances.
Installation
npm install @superutils/core @superutils/promiseUsage
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) // falsePromisE.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, 1100PromisE.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()Enumerations
Classes
Interfaces
Type Aliases
- Config
- DeferredOptions
- DeferredReturn
- IPromisE_Timeout
- OnEarlyFinalize
- PromiseParams
- RetryOptions
- TimeoutFunc
- TimeoutOptions
Variables
Functions
References
default
Renames and re-exports PromisE