conradreuter / cancellationtoken Goto Github PK
View Code? Open in Web Editor NEWA composable token for cancelling asynchronous operations.
License: MIT License
A composable token for cancelling asynchronous operations.
License: MIT License
We have "type": "module"
in the package.json and then are just doing:
import CancellationToken from "cancellationtoken"
console.log(CancellationToken.create) // undefined
But the actual exported object doesn't match the documentation.
When I log the module itself it has an unexpected "default" field which doesn't match the documentation or the type definitions.
Now if I change it to be:
import * as CancellationToken from "cancellationtoken"
console.log(CancellationToken.default.create)
console.log(CancellationToken)
Then it shows there is now an extra "default" field but still, the actual exported type is different, it ends up on default.default
...
This is my current workaround:
import CancellationToken from 'cancellationtoken'
import ct from 'cancellationtoken'
const create = (ct as any).default.create as () => { token: CancellationToken, cancel: (reason?: any) => void; }
Given:
CancellationToken
and arranges to respond to cancelation by attaching something to its whenCancelled
promise,CancellationToken
(e.g. tied to the lifetime of some object) provided to the aforementioned async operation.In the above conditions, the continuation scheduled to handle cancellation cannot be removed, leaving a leak. If this happens repeatedly, the long-lived CancellationToken
's whenCancelled
promise's internal array of continuations simply continues to grow indefinitely until the process runs out of memory.
Incidentally this seems to be a fundamental problem with ECMAScript Promises themselves since any long-lived promise's continuation cannot be canceled.
In .NET, the way we solve this is CancellationToken.Register
(the method we use to execute code when the token is later canceled) returns an IDisposable
which can be disposed in order to cancel the registration, effectively removing the promise continuation from the array and releasing the memory to avoid a leak. Its usage looks like this:
using (cancellationToken.Register(() => cancelAsyncOperation())
{
await asyncOperationCompletion;
return result;
}
Perhaps if instead of exposing as a Promise
directly, you expose a Promise-like type that adds the ability to remove continuations, we can allow consumers of your library to avoid the memory leak.
Awesome library, by the way. I was about to write my own but came across yours on npmjs.org and decided to use yours instead.
Consider the following code:
const error = new CancellationError(null);
const s = String(error);
It seems that the CancellationError
constructor is missing a line like this.name = 'CancellationError';
. For more information, see the MDN documentation of Error.prototype.name
.
The constructor of CancellationError
has the parameter reason: any
, forcing me to pass a value. In most situations, I don't care about why an operation was cancelled, so most constructor calls look like new CancellationError(null)
.
Might it make sense to make this parameter optional?
The npm package includes the .js.map file but not the .ts file. As a result, TS map aware debuggers will report a .ts line number but can't navigate to the .ts file:
Operation cancelled
at new CancellationError (node_modules/cancellationtoken/src/CancellationToken.ts:192:7)
at ChannelClass.tryCancelOffer (node_modules/src/Channel.ts:180:36)
at MultiplexingStreamClass.offerChannelCanceled (node_modules/src/MultiplexingStream.ts:426:17)
at node_modules/src/MultiplexingStream.ts:249:82
at node_modules/cancellationtoken/src/CancellationToken.ts:111:40
at Set.forEach (<anonymous>)
at cancel (node_modules/cancellationtoken/src/CancellationToken.ts:111:24)
at node_modules/cancellationtoken/src/CancellationToken.ts:123:36
at Timeout.task [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:391:19)
Let's remove the .js.map file or add the .ts file.
Example:
token.onCancelled(myFunction)
...
// do work
...
// Ex:
token.removeAllCancelled()
Use case:
A singleton service which calls cancel() first (if exists) and then creates a new token and dispatches work in another singleton service. The expectation is if token.onCancelled is registered it triggers. However, if work completes it can remove onCancelled so it never gets called since there is no need for it anymore.
Hey all, we're using the cancellationtoken library in production for a while now without any issues, it possible to take 2.3 out of RC status and release it?
Thanks!
Hello, thanks for providing this library, it's been very useful for our product!
There is one small thing that would be great to change, when you do CancellationToken.create
it doesn't return a named type but an anonymous type. As we're passing this "type" around between functions I created a small helper:
import CancellationToken from 'cancellationtoken';
export type CancellationTokenSource = {
token: CancellationToken;
cancel: (reason?: any) => void;
};
export default CancellationTokenSource;
Would you be open to change the typing to have CancellationToken.create
return a proper type?
If you're fine with it I can create a PR, I'm just not sure of the naming, CancellationTokenSource is what C# calls it.
Thanks!
Hi,
First of all, great library.
When looking at this (and other) libraries that provide cancellation through timeout, is that I wish to stop the cancellation from occurring when my process ended before the timeout occurred. In .NET, the disposal of the CancellationTokenSource takes care of that. I think this library would benefit also from such a dispose function. Such a disposal would disallow a token to be cancelled, remove any timer, and cleanup any callback registrations.
Your thoughts?
Joost
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.