npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

you-are-cancelled

v2.0.0

Published

An implementation of the cooperative cancellation model that is heavily inspired by the .NET implementation.

Downloads

18

Readme

You Are Cancelled

Available from NPM Built using GitHub Action

An implementation of the cooperative cancellation model that is heavily inspired by the .NET implementation.

Usage

The TL;DR is that there are Cancellation Token Sources where each have a Cancellation Token associated with them. An operation that can be cancelled and spawns one or more async sub-operations would create a Cancellation Token Source and give said sub-operations the resulting Cancellation Token. When interrupted, the operation will request a cancellation using the aforementioned Cancellation Token Source, the associated token will then communicate that cancellation request to all sub-operations allowing them to gracefully abort.

This module can be treated as an ES module:

import { CancellationTokenSource } from 'you-are-cancelled';

This module can also be treated as a CommonJS module:

const { CancellationTokenSource } = require('you-are-cancelled');

Cancellation Token Sources

An operation that can be cancelled and spawns one or more asynchronous sub-operations would create the Cancellation Token Source:

const source = new CancellationTokenSource();

When the operation needs to be cancelled, you can request a cancellation:

setTimeout(function ()
{
  source.cancel('Cancelling operation because it took longer than 5 seconds.');

}, 5000);

Cancellation Tokens

The cancellation token is responsible for propagating the cancellation requested by its associative Cancellation Token Source. Every Cancellation Token Source has a unique token associated with it. You will give this token to any asynchronous operation that can be cancelled:

await getRecordsFromDatabase(source.token);

Important: Do not pass around the Cancellation Token Source!

Reacting to cancellation requests

You can register a callback that will execute when a cancellation has been requested:

token.register(function (error)
{
  // Clean up...
});

Important: If a cancellation has already been requested, the callback will be executed immediately.

It is important that you deregister the callback when the operation completes. Otherwise you may have a potential memory leak, or face unexpected errors because a cancellation request will still execute your callback. You can achieve this easily like this:

const callback = token.register(function ()
{
  // Clean up...
});

try
{
  // Perform operation.
}
catch (error)
{
  // Handle errors.
}
finally
{
  token.deregister(callback);
}

Handling cancellation requests

The cancellation token is also a thenable object, so you can race it against other promises:

try
{
  await Promise.race([operation, token]);
}
catch (error)
{
  if (error instanceof OperationCancellationError)
  {
    // Was cancelled. Could do some clean up here.
  }
  else
  {
    // Operation error.
  }
}

The cancellation token will never resolve; it will only ever be pending or rejected. When a cancellation is requested, the token is rejected with an OperationCancellationError with a message that matches the reason provided when said cancellation was requested.

In addition, you can throw an OperationCancellationError if a cancellation has already been requested:

token.throwIfCancellationRequested();

The Dummy Cancellation Token

When defining an operation that can be cancelled, it is good practice to make the cancellation token optional. The CancellationToken.None dummy token can help you with this - you can use it as a default parameter value so your code can always assume it has a cancellation token to work with:

async function getRecordsFromDatabase(filter, token = CancellationToken.None)
{
  // ...
}

The token state

Each cancellation token has the following state associated with it:

| Flag | Description | | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | isCancelable | Indicates whether the token is capable of being in a cancelled state. Normally this will be true, but for the CancellationToken.None dummy token this will always be false. | | isCancellationRequested | Indicates whether a cancellation has been requested. For the CancellationToken.None dummy token this will always be false. |

Abort Signals

This module was developed before the Abort Controller Interface was introduced. To make the migration simpler, or if you simply prefer using this module, a CancellationToken can be converted to an AbortSignal:

const signal = token.toAbortSignal();

Important: This will return null in a runtime environment where AbortController is not yet supported; it is your responsibility to polyfill that interface if you need to.

Getting started

This module is available through the Node Package Manager (NPM):

npm install you-are-cancelled

Please Note: Versions of Node lower than v12.0.0 are not supported.

Development

Building

You can build UMD and ESM versions of this module that are minified:

npm run build

Testing

This module also has a robust test suite:

npm test

This includes a code quality check using ESLint. Please refer to the .eslintrc files to familiar yourself with the rules.

License

This project is released under the MIT license.