Package Exports
- c-promise2
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (c-promise2) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
SYNOPSIS ✨
CPromise is a subclass of the Promise provided by the environment with some extra features like cancellation, timeouts and progress capturing.
In terms of the library the cancellation means rejection of the deepest promise in the chain with a special error subclass.
It supports cancellation of the whole chain, not just a single promise.
This lib can be used for both backend and frontend development, no any dependencies required.
Why ❓
You may face with a challenge when you need to cancel some long-term asynchronous operation before it will be completed with success or failure, just because the result has lost its relevance to you.
How it works
The deepest pending CPromise in the chain will be rejected will a CanceledError
,
then that chain and each above standing chain will emit cancel
event. This event will be handled by
callbacks attached by onCancel(cb)
method and propagate with signal from AbortController
.
These api can be used simultaneously. The cancel([reason])
method is synchronous and can be called any time.
If cancellation failed (the chain has been already fulfilled) it will return false
.
Features / Advantages
- there are no any dependencies (except [native] Promise)
- browser support
- 🔥 supports cancellation of the whole chain - rejects the deepest pending promise in the chain
- supports onCancel event handler to abort some internal work (clear timers, close requests etc.)
- supports built-in signal interface for API that supports it (like fetch method)
- proper handling of
CanceledError
errors manually thrown inside the chain - 🔥 progress capturing with result scaling to handle progress of the whole chain (including nested promise chains), useful for long-term operations
- ability to install the
weight
for each promise in the chain - ability to attach meta info on each setting of the progress
- the
delay
method to return promise that will be resolved with the value after timeout - static methods
all
,race
support cancellation and will cancel all other pending promises after they resolved - the
catch
method supports error class filtering
Live Example
This is how an abortable fetch (live example) with a timeout might look like
function fetchWithTimeout(url, timeout) {
return new CPromise((resolve, reject, {signal}) => {
fetch(url, {signal}).then(resolve, reject)
}).timeout(timeout)
}
const chain= fetchWithTimeout('http://localhost/', 5000);
// chain.cancel();
Live browser example (jsfiddle.net)
Live nodejs example (jsfiddle.net)

Installation 🔨
- Install for node.js using npm/yarn:
$ npm install c-promise2
$ yarn add c-promise2
The package consists pre-built bundles with umd, cjs, mjs versions which can be found in the ./dist/
directory
- Import the library:
import CPromise from "c-promise2";
// const CPromise = require("c-promise2"); // using require
// import CPromise from "c-promise2/dev"; // development version
CPromise.delay(1000, 'It works!').then(str => console.log('Done', str));
CDN
development UMD version with (additional error handling activated)
production UMD version (or minified ~9KB)
Playground
- Clone https://github.com/DigitalBrainJS/c-promise.git repo
- Run npm install to install dev-dependencies
- Open playground/basic.js file with a basic example
- Run this file using npm run playground or npm run playground:watch command to see the result
Usage example
A font-end example of wrapping fetch to the CPromise and handling cancellation using signals (AbortController)
function cancelableFetch(url) {
return new CPromise((resolve, reject, {signal}) => {
fetch(url, {signal}).then(resolve, reject);
})
}
// URL with 5 seconds delay to respond
const chain= cancelableFetch('https://run.mocky.io/v3/753aa609-65ae-4109-8f83-9cfe365290f0?mocky-delay=5s')
.then(console.log, console.warn);
setTimeout(()=> chain.cancel(), 1000);
Handling cancellation with onCancel
listeners (see the live demo):
import CPromise from "c-promise";
const timestamp= Date.now();
function log(message, ...values){
console.log(`[${Date.now()- timestamp}ms] ${message}`, ...values);
}
const delay= (ms, value)=>{
return new CPromise((resolve, reject, {onCancel}) => {
const timer = setTimeout(resolve, ms, value);
onCancel(() => {
log(`clearTimeout`);
clearTimeout(timer);
})
})
}
const chain = delay(1000, 1).label('first chain')
.then((value)=> delay(1000, value + 1)).label('second chain')
.then((value)=> delay(1000, value + 1)).label('third chain')
.then((value)=> delay(1000, value + 1).label('inner chain')).label('fourth chain')
.then((value)=> delay(1000, value + 1)).label('fifth chain')
.progress((value, scope)=> log(`Pending progress ${value} (${scope.label()})`));
const echoChainState= ()=>console.log(`Is pending: ${chain.isPending}\nIs canceled: ${chain.isCanceled}`);
echoChainState();
chain
.then((value) => {
log(`Done with value '${value}'`); // [1006ms] CanceledError: canceled
}).label('final')
.catch((err)=>{
log(`cancelled with error : ${err} on '${err.scope.label()}'`); // [1006ms] CanceledError: canceled
}, CPromise.CanceledError)
.catch(err=>{
log(`Some other error occurred: ${err}`);
})
.finally(() => {
echoChainState();
});
//setTimeout(()=> chain.cancel(), 3500); // Close the chain after 3500ms
The output of the code above:
Is pending: true
Is canceled: false
[1003ms] Pending progress 0.2 (first chain)
[2004ms] Pending progress 0.4 (second chain)
[3004ms] Pending progress 0.6 (third chain)
[4004ms] Pending progress 0.8 (fourth chain)
[5006ms] Pending progress 1 (fifth chain)
[5006ms] Done with value '5'
Is pending: false
Is canceled: false
Process finished with exit code 0
Uncomment the last line to cancel the chain after 3500ms. The output will be as follows:
Is pending: true
Is canceled: false
[1002ms] Pending progress 0.2 (first chain)
[2003ms] Pending progress 0.4 (second chain)
[3004ms] Pending progress 0.6 (third chain)
[3508ms] clearTimeout
[3509ms] cancelled with error : CanceledError: canceled on 'inner chain'
Is pending: false
Is canceled: true
Process finished with exit code 0
API Reference
Cancellable Promise with extra features
- CPromise
- ~CPromiseScope ⇐
TinyEventEmitter
- new CPromiseScope(resolve, reject, options)
- instance
- .signal :
AbortSignal
- .isPending ⇒
Boolean
- .isCanceled ⇒
Boolean
- .onCancel(listener)
- .progress([value], [data])
- .propagate(type, data) ⇒
CPromiseScope
- .captureProgress() ⇒
CPromiseScope
- .scopes() ⇒
Array.<CPromiseScope>
- .timeout(value) ⇒
Number
|this
- .weight(weight) ⇒
Number
|CPromiseScope
- .label(label) ⇒
Number
|CPromiseScope
- .resolve(value)
- .reject(err)
- .done(err, value)
- .cancel(reason)
- .signal :
- static
- .execute(executor, resolve, reject, options) ⇒
CPromiseScope
- .execute(executor, resolve, reject, options) ⇒
- ~CPromise ⇐
Promise
- new CPromise(executor, options)
- instance
- .isPending ⇒
Boolean
- .isCanceled ⇒
Boolean
- .progress(listener) ⇒
Number
|CPromise
- .captureProgress() ⇒
CPromise
- .cancel(reason) ⇒
Boolean
- .delay(ms) ⇒
CPromise
- .then(onFulfilled, [onRejected]) ⇒
CPromise
- .catch(onRejected, filter) ⇒
CPromise
- .isPending ⇒
- static
- .delay(ms, value) ⇒
CPromise
- .all(thenables) ⇒
CPromise
- .race(thenables) ⇒
CPromise
- .from(thing) ⇒
CPromise
- .delay(ms, value) ⇒
- ~PromiseScopeOptions :
Object
- ~onFulfilled :
function
- ~onRejected :
function
- ~AttachOnCancelHandler :
function
- ~ExecutorAPI :
object
- ~CPromiseExecutorFn :
function
- ~CPromiseExecutorFn :
function
- ~CPromiseOptions :
Object
|String
|Number
- ~CPromiseScope ⇐
CPromise~CPromiseScope ⇐ TinyEventEmitter
Scope for CPromises instances
Kind: inner class of CPromise
Extends: TinyEventEmitter
- ~CPromiseScope ⇐
TinyEventEmitter
- new CPromiseScope(resolve, reject, options)
- instance
- .signal :
AbortSignal
- .isPending ⇒
Boolean
- .isCanceled ⇒
Boolean
- .onCancel(listener)
- .progress([value], [data])
- .propagate(type, data) ⇒
CPromiseScope
- .captureProgress() ⇒
CPromiseScope
- .scopes() ⇒
Array.<CPromiseScope>
- .timeout(value) ⇒
Number
|this
- .weight(weight) ⇒
Number
|CPromiseScope
- .label(label) ⇒
Number
|CPromiseScope
- .resolve(value)
- .reject(err)
- .done(err, value)
- .cancel(reason)
- .signal :
- static
- .execute(executor, resolve, reject, options) ⇒
CPromiseScope
- .execute(executor, resolve, reject, options) ⇒
new CPromiseScope(resolve, reject, options)
Constructs PromiseScope instance
Param | Type |
---|---|
resolve | function |
reject | function |
options | PromiseScopeOptions |
cPromiseScope.signal : AbortSignal
get promise abort signal object
Kind: instance property of CPromiseScope
cPromiseScope.isPending ⇒ Boolean
indicates if the promise is pending
Kind: instance property of CPromiseScope
cPromiseScope.isCanceled ⇒ Boolean
indicates if the promise is pending
Kind: instance property of CPromiseScope
cPromiseScope.onCancel(listener)
registers the listener for cancel event
Kind: instance method of CPromiseScope
Param | Type |
---|---|
listener | function |
cPromiseScope.progress([value], [data])
Set promise progress
Kind: instance method of CPromiseScope
Param | Type | Description |
---|---|---|
[value] | Number |
a number between [0, 1] |
[data] | * |
any data to send for progress event listeners |
cPromiseScope.propagate(type, data) ⇒ CPromiseScope
emit propagate event that will propagate through each promise scope in the chain (bubbling)
Kind: instance method of CPromiseScope
Param | Type | Default | Description |
---|---|---|---|
type | String | Symbol |
some type to identify the data kind | |
data | * |
|
some data |
cPromiseScope.captureProgress() ⇒ CPromiseScope
capture initial progress state of the chain
Kind: instance method of CPromiseScope
cPromiseScope.scopes() ⇒ Array.<CPromiseScope>
Returns all parent scopes that are in pending state
Kind: instance method of CPromiseScope
cPromiseScope.timeout(value) ⇒ Number
| this
timeout before the promise will be canceled
Kind: instance method of CPromiseScope
Param | Type | Description |
---|---|---|
value | Number |
timeout in ms |
cPromiseScope.weight(weight) ⇒ Number
| CPromiseScope
Sets the promise weight in progress capturing process
Kind: instance method of CPromiseScope
Returns: Number
| CPromiseScope
- returns weight if no arguments were specified
Param | Type | Description |
---|---|---|
weight | Number |
any number grater or equal 0 |
cPromiseScope.label(label) ⇒ Number
| CPromiseScope
Sets the promise label
Kind: instance method of CPromiseScope
Returns: Number
| CPromiseScope
- returns weight if no arguments were specified
Param | Type | Description |
---|---|---|
label | String |
any string |
cPromiseScope.resolve(value)
Resolves the promise with given value
Kind: instance method of CPromiseScope
Param |
---|
value |
cPromiseScope.reject(err)
Rejects the promise with given error
Kind: instance method of CPromiseScope
Param |
---|
err |
cPromiseScope.done(err, value)
Resolves or rejects the promise depending on the arguments
Kind: instance method of CPromiseScope
Param | Description |
---|---|
err | error object, if specified the promise will be rejected with this error, resolves otherwise |
value |
cPromiseScope.cancel(reason)
throws the CanceledError that cause promise chain cancellation
Kind: instance method of CPromiseScope
Param | Type |
---|---|
reason | String | Error |
CPromiseScope.execute(executor, resolve, reject, options) ⇒ CPromiseScope
Executes the promise executor in the PromiseScope context
Kind: static method of CPromiseScope
Param | Type |
---|---|
executor | CPromiseExecutorFn |
resolve | |
reject | |
options |
CPromise~CPromise ⇐ Promise
CPromise class
Kind: inner class of CPromise
Extends: Promise
- ~CPromise ⇐
Promise
- new CPromise(executor, options)
- instance
- .isPending ⇒
Boolean
- .isCanceled ⇒
Boolean
- .progress(listener) ⇒
Number
|CPromise
- .captureProgress() ⇒
CPromise
- .cancel(reason) ⇒
Boolean
- .delay(ms) ⇒
CPromise
- .then(onFulfilled, [onRejected]) ⇒
CPromise
- .catch(onRejected, filter) ⇒
CPromise
- .isPending ⇒
- static
- .delay(ms, value) ⇒
CPromise
- .all(thenables) ⇒
CPromise
- .race(thenables) ⇒
CPromise
- .from(thing) ⇒
CPromise
- .delay(ms, value) ⇒
new CPromise(executor, options)
Constructs new CPromise instance
Param | Type | Description |
---|---|---|
executor | CPromiseExecutorFn |
promise executor function that will be invoked in the context of the new CPromiseScope instance |
options | CPromiseOptions |
cPromise.isPending ⇒ Boolean
indicates if the promise is pending
Kind: instance property of CPromise
cPromise.isCanceled ⇒ Boolean
indicates if promise has been canceled
Kind: instance property of CPromise
cPromise.progress(listener) ⇒ Number
| CPromise
returns chains progress synchronously or adds a progress event listener if the argument was specified
Kind: instance method of CPromise
Param | Type |
---|---|
listener | function |
cPromise.captureProgress() ⇒ CPromise
Kind: instance method of CPromise
See: CPromiseScope.captureProgress
cPromise.cancel(reason) ⇒ Boolean
cancel the promise chain with specified reason
Kind: instance method of CPromise
Returns: Boolean
- true if success
Param | Type |
---|---|
reason | String |
cPromise.delay(ms) ⇒ CPromise
Returns a chain that will be resolved after specified timeout
Kind: instance method of CPromise
Param | Type |
---|---|
ms | Number |
cPromise.then(onFulfilled, [onRejected]) ⇒ CPromise
returns a CPromise. It takes up to two arguments: callback functions for the success and failure cases of the Promise.
Kind: instance method of CPromise
Param | Type |
---|---|
onFulfilled | onFulfilled |
[onRejected] | onRejected |
cPromise.catch(onRejected, filter) ⇒ CPromise
Catches rejection with optionally specified Error class
Kind: instance method of CPromise
Param | Type |
---|---|
onRejected | function |
filter | Error |
CPromise.delay(ms, value) ⇒ CPromise
Returns a CPromise that will be resolved after specified timeout
Kind: static method of CPromise
Param | Type | Description |
---|---|---|
ms | Number |
delay before resolve the promise with specified value |
value |
CPromise.all(thenables) ⇒ CPromise
Returns a single CPromise that resolves to an array of the results of the input promises. If one fails then other promises will be canceled immediately
Kind: static method of CPromise
Param | Type |
---|---|
thenables | Iterable |
CPromise.race(thenables) ⇒ CPromise
returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise. Other pending promises will be canceled immediately
Kind: static method of CPromise
Param | Type |
---|---|
thenables | Iterable |
CPromise.from(thing) ⇒ CPromise
Converts thing to CPromise. If thing if a thenable with cancel method it will be called on cancel event
Kind: static method of CPromise
Param | Type |
---|---|
thing | * |
CPromise~PromiseScopeOptions : Object
Kind: inner typedef of CPromise
Properties
Name | Type | Description |
---|---|---|
label | String |
the label for the promise |
weight= | Number |
1 - the progress weight of the promise |
timeout= | Number |
0 - max pending time |
CPromise~onFulfilled : function
Kind: inner typedef of CPromise
this: CPromiseScope
Param | Type |
---|---|
value | |
scope | CPromiseScope |
CPromise~onRejected : function
Kind: inner typedef of CPromise
this: CPromiseScope
Param | Type |
---|---|
err | |
scope | CPromiseScope |
CPromise~AttachOnCancelHandler : function
Kind: inner typedef of CPromise
CPromise~ExecutorAPI : object
Kind: inner typedef of CPromise
Properties
Name | Type |
---|---|
onCancel | AttachOnCancelHandler |
CPromise~CPromiseExecutorFn : function
Kind: inner typedef of CPromise
this: CPromiseScope
Param | Type |
---|---|
resolve | function |
reject | function |
api | ExecutorAPI |
CPromise~CPromiseExecutorFn : function
Kind: inner typedef of CPromise
Param | Type |
---|---|
resolve | function |
reject | function |
CPromise~CPromiseOptions : Object
| String
| Number
If value is a number it will be considered as the value for timeout option If value is a string it will be considered as label
Kind: inner typedef of CPromise
License
The MIT License Copyright (c) 2020 Dmitriy Mozgovoy robotshara@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.