cancellation-context
v0.2.11
Published
Promise-cancellation made easy. Cancel one or more promises in a given context.
Downloads
8
Maintainers
Readme
cancellation-context
Promise-cancellation made easy. Cancel one or more promises in a given context.
Install
npm i cancellation-context
Usage
Create a new context by calling the exported factory function.
const CancellationContext = require('cancellation-context');
const context = CancellationContext();
Once you have a context, you can create new "cancellable-promise" instances within that context by calling context.Cancellable
with promise-thunk factory.
Note: Promises are eager by design and don't naturally lend themselve to cancellation. As such, arbitrary promises are not cancellable and the onus is the author to write cancellable promise implementations. No library, including this one, will be able to solve for that unless there are some fundamental changes to the JavaScript spec.
The cancellation-context
library attempts to make the authoring of cancellable-promises as easy as possible by designing around the idea of promise-thunks.
The recommended pattern is as follows:
CancellableFactory = ({{ ...args }}) => onCancel => {{ promise }};
For example...
const context = require('cancellation-context')();
const MyCancellableFactory = msg => onCancel => new Promise((resolve, reject) => {
const t = setTimeout(() => resolve(msg), 1000);
onCancel(reason => {
clearTimeout(t);
resolve(reason);
});
});
(async () => {
const myCancellable = context.Cancellable(MyCancellableFactory('success!'));
setTimeout(() => myCancellable.cancel('cancelled!'), 500);
console.log(await myCancellable); // => 'cancelled!'
})();
By leveraging a thunk pattern, you can maintain composability while supporting the need for an onCancel
hook.
API
cancellation-context
- cancellation-context
- module.exports ⇒ CancellationContext ⏏
- ~CancellationContext
- ~CancellationError
- ~TimeoutError
- ~Cancellable(PromiseThunkFactory) ⇒ CancellablePromise
- ~Perishable(PromiseThunkFactory) ⇒ PerishablePromise
- ~cancel(promise, reason) ⇒ void
- ~cancelAll(reason) ⇒ void
- ~delay(ms) ⇒ function
- ~timeout(ms) ⇒ function
- ~CancellableDelay(ms) ⇒ function
- ~CancellableTimeout(ms) ⇒ function
- ~PerishableTimeout(ms, ttl) ⇒ function
- ~PerishableDelay(ms, ttl) ⇒ function
- module.exports ⇒ CancellationContext ⏏
module.exports ⇒ CancellationContext ⏏
Factory function for creating CancellationContext instances.
Kind: Exported member
module.exports~CancellationContext
Kind: inner class of module.exports
See: CancellationContextFactory
new CancellationContext()
CancellationContext
is a private class. Use exported CancellationContextFactory
function for instantiation.
module.exports~CancellationError
Kind: inner class of module.exports
Implements: Error
new CancellationError()
An error class used for indicating cancellation events.
module.exports~TimeoutError
Kind: inner class of module.exports
Implements: Error
new TimeoutError()
An error class used for indicating timeout events.
module.exports~Cancellable(PromiseThunkFactory) ⇒ CancellablePromise
Given a PromiseThunkFactory which accepts on onCancel
hook, returns a CancellablePromise.
Kind: inner method of module.exports
Returns: CancellablePromise - A CancellablePromise
is a promise with an additional cancel
method attached.
| Param | Type | | --- | --- | | PromiseThunkFactory | function |
module.exports~Perishable(PromiseThunkFactory) ⇒ PerishablePromise
Given a PromiseThunkFactory which accepts on onCancel
hook, returns a PerishablePromise.
Kind: inner method of module.exports
Returns: PerishablePromise - A PerishablePromise
is a CancellablePromise
which will be automatically cancelled after a specified amount of time.
| Param | Type | | --- | --- | | PromiseThunkFactory | function |
module.exports~cancel(promise, reason) ⇒ void
Given promise
and reason
calls canceller on promise
with reason
.
Kind: inner method of module.exports
| Param | Type | Description | | --- | --- | --- | | promise | Promise | CancellablePromise to be cancelled | | reason | 'string' | 'Error' | reason for cancellation |
module.exports~cancelAll(reason) ⇒ void
Calls cancel
method with reason
on every CancellablePromise associated with the context instance.
Kind: inner method of module.exports
| Param | Type | Description | | --- | --- | --- | | reason | 'string' | 'Error' | reason for cancellation |
module.exports~delay(ms) ⇒ function
A cancellable delay implementation which resolves after given number of milliseconds.
Kind: inner method of module.exports
Returns: function - Returns function which accepts onCancel
hook.
| Param | Type | Description | | --- | --- | --- | | ms | number | Number of milliseconds to wait |
Example
const cancellableDelay = context.Cancellable(context.delay(1500));
setTimeout(() => cancellableDelay.cancel(), 1000);
await cancellableDelay;
module.exports~timeout(ms) ⇒ function
A cancellable timeout implementation which resolves after given number of milliseconds.
Kind: inner method of module.exports
Returns: function - Returns function which accepts onCancel
hook.
| Param | Type | Description | | --- | --- | --- | | ms | number | Number of milliseconds to wait |
Example
const cancellableTimeout = context.Cancellable(context.delay(1500));
setTimeout(() => cancellableTimeout.cancel(), 1000);
await cancellableTimeout;
module.exports~CancellableDelay(ms) ⇒ function
A CancellableFactory which resolves after given number of milliseconds.
Kind: inner method of module.exports
Returns: function - Returns function which accepts onCancel
hook.
| Param | Type | Description | | --- | --- | --- | | ms | number | Number of milliseconds to wait |
Example
const cancellableDelay = context.CancellableDelay(1500));
setTimeout(() => cancellableDelay.cancel(), 1000);
await cancellableDelay;
module.exports~CancellableTimeout(ms) ⇒ function
A CancellableFactory which rejects after given number of milliseconds.
Kind: inner method of module.exports
Returns: function - Returns function which accepts onCancel
hook.
| Param | Type | Description | | --- | --- | --- | | ms | number | Number of milliseconds to wait |
Example
const cancellableTimeout = context.CancellableTimeout(1500));
setTimeout(() => cancellableTimeout.cancel(), 1000);
await cancellableTimeout;
module.exports~PerishableTimeout(ms, ttl) ⇒ function
A PerishableFactory which rejects after given number of milliseconds.
Kind: inner method of module.exports
Returns: function - Returns function which accepts onCancel
hook.
| Param | Type | Description | | --- | --- | --- | | ms | number | Number of milliseconds to wait | | ttl | number | Number of milliseconds until cancelled |
Example
const cancellableTimeout = context.PerishableTimeout(1500, 1000);
await cancellableTimeout;
module.exports~PerishableDelay(ms, ttl) ⇒ function
A PerishableFactory which resolves after given number of milliseconds.
Kind: inner method of module.exports
Returns: function - Returns function which accepts onCancel
hook.
| Param | Type | Description | | --- | --- | --- | | ms | number | Number of milliseconds to wait | | ttl | number | Number of milliseconds until cancelled |
Example
const cancellableDelay = context.PerishableDelay(1500, 1000);
await cancellableDelay;
Examples
Cancellable Delay
const context = require('cancellation-context')();
(async () => {
try {
const ttl = 1000; // try increasing to 10000
console.log(await context.PerishableTimeout(1500, ttl).then(() => 'success'));
} catch (e) {
console.error('Boom!', e);
}
})();
Manual Cancellation
const context = require('cancellation-context')();
const sleep = ms => onCancel => {
return new Promise((resolve, reject) => {
const t = setTimeout(() => resolve('success'), ms);
onCancel(error => {
clearTimeout(t);
reject(error);
});
});
};
(async () => {
try {
const promise = context.Cancellable(sleep(1500));
const handle = setTimeout(() => context.cancel(promise), 1000); // try increasing to 10000
console.log('Success!', await promise);
clearTimeout(handle);
} catch (e) {
console.error('Boom!', e);
}
})();
Async Iterables
const context = require('cancellation-context')();
(async () => {
async function* loop() {
while (true) {
const promises = [
context.CancellableTimeout(500).then(() => (console.log('done'), 'success')),
context.CancellableTimeout(1000).then(() => (console.log('done'), 'success')),
context.CancellableTimeout(1500).then(() => (console.log('done'), 'success'))
];
yield await Promise.all(promises);
}
}
setTimeout(() => context.cancelAll(), 4000);
try {
for await (const result of loop()) {
console.log(result);
}
} catch (e) {
context.cancelAll();
console.error('Boom!', e);
}
})();