Cancelable promise with progress capturing, pause, timeouts, signals, data flows and decorators support
npm install c-promise2

!npm
!npm bundle size
!David

CPromise class - an advanced version of the built-in Promise that supports:
all/race/allSettled support cancellation.
all & allSettled method support concurrency limitation and generators as promise producers
generators/yield as an alternative of async/await
pause & resume ability
AbortController support (providing & subscribing for multiple signals sources)
bash
$ npm install c-promise2
`
yarn:
`bash
$ yarn add c-promise2
`
CDN:
- production UMD version
(or minified ~11KB) - provides the CPromise class
as the default export, other exports values declared as static properties
- production CommonJS version
- production ESM version
$3
- Import CPromise class:
``js
import { CPromise } from "c-promise2";
``
- Use CPromise constructor instead of Promise. To terminate internal async tasks (timers, request, streams etc.) gracefully subscribe your cleanup handler with onCancel(handler):
``js
const doTask = (ms)=>{
return CPromise((resolve, reject, {onCancel})=>{
const timer= setTimeout(resolve, ms, "myValue");
onCancel(()=> clearTimeout(timer));
});
}
const promise = doTask(1000).then(console.log);
``
Or/and turn generators to async functions with CPromise.promisify to write cancellable async code in flat style:
``js
const doTask = CPromise.promisify(function*(ms){
yield CPromise.delay(ms);
return "myValue";
});
const promise = doTask(1000).then(console.log);
``
- Call promise.cancel([reason]) to cancel pending promise chain by rejecting the deepest
pending promise in the chain with a special CanceledError reason:
``js
promise.cancel("My bad");
``
$3
#### Building plain CPromise chains using then
Codesandbox Live Demo
``javascript
import { CPromise } from "c-promise2";
const promise= new CPromise((resolve, reject, {onCancel, onPause, onResume})=>{
onCancel(()=>{
//optionally some code here to abort your long-term task (abort request, stop timers etc.)
});
}).then(
value => console.log(Done: ${value}),
(err, scope) => {
console.warn(Failed: ${err}); // Failed: CanceledError: canceled
console.log('chain isCanceled:', promise.isCanceled); // true
console.log('promise isCanceled:', scope.isCanceled); // true
}
);
console.log('isPromise:', promise instanceof Promise); // true
setTimeout(()=> promise.cancel(), 1000);
``
Log:
``
isPromise: true
Failed: CanceledError: canceled
chain isCanceled: true
promise isCanceled: true
``
#### Writing flat code using generators
Codesandbox Live Demo
``javascript
import { CPromise } from "c-promise2";
const sayHello = CPromise.promisify(function* (v) {
for (let i = 0; i < 3; i++) {
console.log(Hello [${i}]);
yield CPromise.delay(1000);
}
return v + 1;
});
const p = sayHello(5)
.then(function* (v) {
console.log(Then);
yield CPromise.delay(1000);
return v + 1;
})
.then((v) => console.log(Done: ${v}));
// setTimeout(() => p.cancel(), 1000); stop trying
``
#### Abortable fetch with timeout
This is how an abortable fetch (live example) with a timeout might look like
``javascript
function fetchWithTimeout(url, {timeout, ...fetchOptions}= {}) {
return new CPromise((resolve, reject, {signal}) => {
fetch(url, {...fetchOptions, signal}).then(resolve, reject)
}, {timeout, nativeController: true})
}
const promise= fetchWithTimeout('http://localhost/', {timeout: 5000})
.then(response => response.json())
.then(data => console.log(Done: , data), err => console.log(Error: , err))
setTimeout(()=> promise.cancel(), 1000);
// you able to call cancel() at any time to cancel the entire chain at any stage
// the related network request will also be aborted
``
#### Note
You can use the cp-fetch which provides a ready to use
CPromise wrapper for cross-platform fetch API, or cp-axios wrapper for axios with powers of CPromise.
.then method behavior notes
The behavior of the method is slightly different from native Promise.
In the case when you cancel the chain after it has been resolved within one eventloop tick,
onRejected will be called with a CanceledError instance, instead of onFulfilled.
This prevents the execution of unwanted code in the next eventloop tick if
the user canceled the promise immediately after the promise was resolved,
during the same eventloop tick.
Ecosystem
#### React
* use-async-effect2 - feature-rich React async hooks that built on top of the cancellable promises (CPromise)
#### Data fetching
* cp-axios - axios cancellable wrapper that supports CPromise context. Can be directly used in use-async-effect2 or general CPromise context
* cp-fetch - cross-platform fetch wrapper that can be used in cooperation with use-async-effect2 or general CPromise chains
#### Backend
* cp-koa - a wrapper for koa` that adds cancellable middlewares/routes to the framework