What is @open-draft/deferred-promise?
@open-draft/deferred-promise is a utility library that provides a way to create and manage deferred promises. This can be particularly useful in scenarios where you need to create a promise and resolve or reject it at a later time, outside of the initial promise executor function.
What are @open-draft/deferred-promise's main functionalities?
Creating a Deferred Promise
This feature allows you to create a deferred promise that can be resolved or rejected at a later time. The code sample demonstrates creating a deferred promise, resolving it after a timeout, and then using the promise in an async function.
const { DeferredPromise } = require('@open-draft/deferred-promise');
const deferred = new DeferredPromise();
// You can resolve or reject the promise later
setTimeout(() => {
deferred.resolve('Resolved value');
}, 1000);
// Use the promise
async function main() {
const result = await deferred;
console.log(result); // 'Resolved value'
}
main();
Handling Rejection
This feature allows you to handle the rejection of a deferred promise. The code sample demonstrates creating a deferred promise, rejecting it after a timeout, and then handling the rejection in an async function.
const { DeferredPromise } = require('@open-draft/deferred-promise');
const deferred = new DeferredPromise();
// You can resolve or reject the promise later
setTimeout(() => {
deferred.reject(new Error('Something went wrong'));
}, 1000);
// Use the promise
async function main() {
try {
const result = await deferred;
} catch (error) {
console.error(error.message); // 'Something went wrong'
}
}
main();
Other packages similar to @open-draft/deferred-promise
p-defer
p-defer is a similar utility that allows you to create deferred promises. It provides a simple API to create a deferred promise and resolve or reject it later. Compared to @open-draft/deferred-promise, p-defer is more widely used and has a more established presence in the npm ecosystem.
deferred
deferred is another package that provides deferred promise functionality. It offers a similar API to @open-draft/deferred-promise but includes additional utilities for working with promises. It is a more feature-rich alternative but may be more complex to use.
Deferred Promise
The DeferredPromise
class is a Promise-compatible abstraction that defers resolving/rejecting promises to another closure. This class is primarily useful when one part of your system establishes as promise but another part of your system fulfills it.
This class is conceptually inspired by the createDeferredPromise()
internal utility in Node.js. Unlike the Node.js implementation, however, DeferredProimse
extends a native Promise
, allowing the consumer to handle deferred promises like regular promises (no .promise
instance nesting).
Getting started
npm install @open-draft/deferred-promise
Documentation
createDeferredExecutor()
Creates a Promise executor function that delegates its resolution to the current scope.
import { createDeferredExecutor } from '@open-draft/deferred-promise'
const executor = createDeferredExecutor()
const promise = new Promise(executor)
executor.resolve('hello')
Deferred executor allows you to control any promise remotely and doesn't affect the Promise instance in any way. Similar to the DeferredPromise
instance, the deferred executor exposes additional promise properties like state
, rejectionReason
, resolve
, and reject
. In fact, the DeferredPromise
class is implemented on top of the deferred executor.
const executor = createDeferredExecutor()
const promise = new Promise(executor)
executor.reject('reason')
nextTick(() => {
console.log(executor.rejectionReason)
})
DeferredExecutor.state
<"pending" | "fulfilled" | "rejected">
Default: "pending"
const executor = createDeferredExecutor()
const promise = new Promise(executor)
console.log(executor.state)
Calling resolve()
and reject()
methods of the executor transitions the state to "fulfilled" and "rejected" respectively.
DeferredExecutor.resolve()
Resolves the promise with a given value.
const executor = createDeferredExecutor()
const promise = new Promise(executor)
console.log(executor.state)
executor.resolve()
console.log(executor.state)
nextTick(() => {
console.log(executor.state)
})
DeferredExecutor.reject()
Rejects the promise with a given reason.
const executor = createDeferredExecutor()
const promise = new Promise(executor)
executor.reject(new Error('Failed to fetch'))
nextTick(() => {
console.log(executor.state)
console.log(executor.rejectionReason)
})
You can access the rejection reason of the promise at any time by the rejectionReason
property of the deferred executor.
DeferredExecutor.rejectionReason
Returns the reason of the promise rejection. If no reason has been provided to the reject()
call, undefined
is returned instead.
const executor = createDeferredExecutor()
const promise = new Promise(executor)
promise.reject(new Error('Internal Server Error'))
nextTick(() => {
console.log(promise.rejectionReason)
})
Class: DeferredPromise
new DefferedPromise()
Creates a new instance of a deferred promise.
import { DeferredPromise } from '@open-draft/deferred-promise'
const promise = new DeferredPromise()
A deferred promise is a Promise-compatible class that constructs a regular Promise instance under the hood, controlling it via the deferred executor.
A deferred promise is fully compatible with the regular Promise, both type- and runtime-wise, e.g. a deferred promise can be chained and awaited normally.
const promise = new DefferredPromise()
.then((value) => value.toUpperCase())
.then((value) => value.substring(0, 2))
.catch((error) => console.error(error))
await promise
Unlike the regular Promise, however, a deferred promise doesn't accept the executor
function as the constructor argument. Instead, the resolution of the deferred promise is deferred to the current scope (thus the name).
function getPort() {
const portPromise = new DeferredPromise()
port.on('open', (port) => {
portPromise.resolve(port)
})
return portPromise
}
Use the resolve()
and reject()
methods of the deferred promise instance to resolve and reject that promise respectively.
deferredPromise.state
See DeferredExecutor.state
deferredPromise.resolve()
See DeferredExecutor.resolve()
deferredPromise.reject()
See DeferredExecutor.reject()
deferredPromise.rejectionReason
See DeferredExecutor.rejectionReason
Mentions
- Jonas Kuske for the phenomenal work around improving Promise-compliance.