Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/alkemics/CancelablePromise

A simple Cancelable Promise
https://github.com/alkemics/CancelablePromise

Last synced: about 2 months ago
JSON representation

A simple Cancelable Promise

Awesome Lists containing this project

README

        

# cancelable-promise

[![GitHub license](https://img.shields.io/github/license/alkemics/CancelablePromise)](https://github.com/alkemics/CancelablePromise/blob/master/LICENSE) [![npm version](https://img.shields.io/npm/v/cancelable-promise)](https://www.npmjs.com/package/cancelable-promise) [![Unit tests](https://github.com/alkemics/CancelablePromise/workflows/Unit%20tests/badge.svg?branch=master)](https://github.com/alkemics/CancelablePromise/actions?query=workflow%3A%22Unit+20tests%22) [![Cypress tests](https://github.com/alkemics/CancelablePromise/workflows/Cypress%20tests/badge.svg?branch=master)](https://github.com/alkemics/CancelablePromise/actions?query=workflow%3A%22Cypress+tests%22) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/alkemics/CancelablePromise/pulls)

A simple Cancelable Promise.

This package is based on ES Promise.

- See [caniuse](https://caniuse.com/#search=Promise) for browser support
- See [core-js](https://github.com/zloirock/core-js#ecmascript-promise) for polyfills
- For example, you can use https://polyfill.io/v3/polyfill.min.js?features=Promise%2CPromise.prototype.finally for Internet Explorer 11

FYI, you can cancel a fetch request with AbortController & AbortSignal.

- See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
- See [caniuse](https://caniuse.com/#feat=abortcontroller)

## Table of Contents

- [Install](#install)
- [Usage](#usage)
- [Basic example](#basic-example)
- [NodeJS](#nodejs)
- [Browser](#browser)
- [API](#api)
- [cancelable](#cancelable)
- [CancelablePromise](#cancelablepromise)
- [CancelablePromise.cancel](#cancelablepromisecancel)
- [CancelablePromise.isCanceled](#cancelablepromiseiscanceled)
- [Static methods](#static-methods)
- [Scripts](#scripts)
- [Build](#build)
- [Tests](#tests)
- [End-to-end tests](#end-to-end-tests)
- [Contributing](#contributing)
- [Contributors](#contributors)
- [Code of conduct](#code-of-conduct)
- [License](#license)

## Install

```
npm install --save cancelable-promise
```

## Usage

CancelablePromise acts like an ES Promise: you can use `Promise.all`, `Promise.race` with your CancelablePromise for example. The only difference is you'll have a `cancel` method on your promise to cancel future execution of `then` or `catch` functions. CancelablePromise will also cancel all callbacks attached to new promises returned by `then`/`catch`.

### Basic example

```javascript
import { cancelable, CancelablePromise } from 'cancelable-promise';

const promises = [
cancelable(new Promise((resolve) => setTimeout(resolve, 1))),
new CancelablePromise((resolve) => setTimeout(resolve, 1)),
];

for (const promise of promises) {
promise.then(() => console.log('not logged'));
promise.cancel();
}
// Nothing will be logged
```

### NodeJS

```javascript
const { cancelable } = require('cancelable-promise');
cancelable(new Promise((resolve) => resolve('ok')));
```

### Browser

```html

const { cancelable } = window.CancelablePromise;
cancelable(new Promise((resolve) => resolve('ok')));

```

```html

import { cancelable } from 'https://unpkg.com/[email protected]/esm/CancelablePromise.min.mjs';
cancelable(new Promise((resolve) => resolve('ok')));

```

## API

### cancelable

```javascript
import { cancelable } from 'cancelable-promise';

/**
* @param {Promise} arg - a native Promise
* @returns {CancelablePromise}
*/
cancelable(
new Promise((resolve) => {
resolve('ok');
})
);
```

### CancelablePromise

```javascript
import CancelablePromise from 'cancelable-promise';

/**
* @param {(resolve, reject, onCancel) => void} arg - an augmented promise executor
* @returns {CancelablePromise}
*/
const promise = new CancelablePromise((resolve, reject, onCancel) => {
const worker = new Worker('some-script.js');

onCancel(() => {
worker.terminate();
});

worker.onmessage = (event) => resolve(event.data);
worker.onerror = (error) => reject(error);
});

promise.cancel(); // It will execute the callback passed to onCancel
```

_`onCancel` callback is working as in [p-cancelable](https://github.com/sindresorhus/p-cancelable)_

### cancelablePromise.cancel

```javascript
/**
* @returns {void}
*/
cancelablePromise.cancel();
```

### cancelablePromise.isCanceled

```javascript
/**
* @returns {boolean}
*/
cancelablePromise.isCanceled();
```

### cancelablePromise.finally

```javascript
/**
* @param {() => void} onFinally callback
* @param {boolean} runWhenCanceled force finally execution on cancel
* @returns {void}
*/
cancelablePromise.finally(() => {});

// You can release prematurely resources for a long running task
// by forcing finnaly callback execution when cancelling a promise
let worker;
const promise = cancelable(
new Promise((resolve, reject) => {
worker = new Worker('some-script.js');
worker.onmessage = (event) => {
resolve(event.data); // never executed
};
worker.onerror = (error) => {
reject(error); // never executed
};
})
)
.then(() => {
console.log('never logged');
})
.finally(
() => {
console.log('executed');
if (worker) {
worker.terminate();
worker = null;
}
},
// runWhenCanceled boolean
true
);

promise.cancel();
```

### Static methods

Same as Promise static methods.

```javascript
import CancelablePromise from 'cancelable-promise';

CancelablePromise.resolve();
CancelablePromise.reject();
CancelablePromise.all([promise1, promise2]);
CancelablePromise.race([promise1, promise2]);
CancelablePromise.allSettled([promise1, promise2]);
```

You can still use the native Promise API and wrap your promise:

```javascript
import { cancelable } from 'cancelable-promise';

cancelable(Promise.all([promise1, promise2]));
cancelable(Promise.race([promise1, promise2]));
cancelable(Promise.allSettled([promise1, promise2]));
```

#### CancelablePromise.isCancelable

Returns `true` if parameter is a cancelable promise.

```javascript
import { cancelable, CancelablePromise } from 'cancelable-promise';

CancelablePromise.isCancelable(cancelable(new Promise(() => {}))); // true
CancelablePromise.isCancelable(new CancelablePromise(() => {})); // true
CancelablePromise.isCancelable(new Promise(() => {})); // false
CancelablePromise.isCancelable(undefined); // false
CancelablePromise.isCancelable({ cancel() {} }); // false
```

### Utils

#### isCancelablePromise

Same as `CancelablePromise.isCancelable`, it returns `true` if parameter is a cancelable promise.

```javascript
import {
cancelable,
CancelablePromise,
isCancelablePromise,
} from 'cancelable-promise';

isCancelablePromise(cancelable(new Promise(() => {}))); // true
isCancelablePromise(new CancelablePromise(() => {})); // true
isCancelablePromise(new Promise(() => {})); // false
isCancelablePromise(undefined); // false
isCancelablePromise({ cancel() {} }); // false
```

## Scripts

### Build

Run babel

```
npm run build
```

### Tests

Run `eslint` and `jest`

```shell
npm test
```

### End-to-end tests

Run `cypress` tests

```shell
npm run test:e2e
```

## Contributing

Feel free to dive in! [Open an issue](https://github.com/alkemics/CancelablePromise/issues) or [submit PRs](https://github.com/alkemics/CancelablePromise/compare).

### Contributors

This project exists thanks to all [the people who contribute](https://github.com/alkemics/CancelablePromise/graphs/contributors).

## Code of conduct

[Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).

## License

[MIT License](LICENSE) © Alkemics