JSPM

  • Created
  • Published
  • Downloads 125
  • Score
    100M100P100Q81447F
  • License MIT

Cancelable promise with progress capturing, pause, timeouts, signals, data flows and decorators support

Package Exports

  • c-promise2

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (c-promise2) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Build Status Coverage Status npm npm bundle size David Stars

Table of contents

SYNOPSIS ✨

CPromise library provides an advanced version of the built-in Promise by subclassing. You might be interested in using it if you need:

  • cancel the promise through rejection (including nested)
  • cancel async tasks inside React components (useful to cancel internal code when components unmounts)
    • with built-in decorators for class components
    • with useAsyncEffect&useAsyncCallback hooks provided by useAsyncEffect2 package
  • cancel network requests with promises, which allows the network request to be automatically aborted when the parent async function is canceled:
  • control cancellation flow to write really complicated async flows with cancelation ability.
  • define atomic promise chains that cannot be canceled in the middle of execution from upper chains
  • AbortController support for promises
  • some way to make cancellation declarative (with method decorators)
  • capture promise chain progress with defining progress impact for each promise (default 1)
  • generators support to write a flat code in the same way as async&await do, but with CPromise features support
  • pause/resume the promise
  • pending timeout
  • concurrent limitation for all and allSettled methods with mapper reducer
  • advanced signal communication

In terms of the library the cancellation means rejection with a special error subclass.

Codesandbox Live Demo

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

CPromise fully supports writing "flat" cancellable code:

Codesandbox Live Demo

const p= CPromise.run(function*(){
  yield CPromise.delay(1000);
  return 1;
}).then(function*(v){
  for(let i=0; i<3; i++) {
    console.log(`delay [${i}]`);
    yield CPromise.delay(500);
  }
  return v + 2;
}).then(v=> console.log(`Done: ${v}`));

//setTimeout(()=> p.cancel(), 1000);

You can use decorators to cancel asynchronous tasks inside React components when unmounted, thereby preventing the well-known React leak warning from appearing:

Codesandbox Live Demo

import React, { Component } from "react";
import { ReactComponent, timeout, cancel } from "c-promise2";
import cpFetch from "cp-fetch";

@ReactComponent
export class FetchComponent extends React.Component {
  state = {text: "fetching..."};

  @timeout(5000)
  *componentDidMount() {
    const response = yield cpFetch(this.props.url);
    this.setState({ text: `json: ${yield response.text()}` });
  }

  render() {
    return (
      <div>
        <span>{this.state.text}</span>
        <button onClick={() => cancel.call(this)}>Cancel request</button>
      </div>);
  }
}

If you prefer function components you can use use-async-effect2 package that decorates CPromise into custom React hooks - useAsyncEffect and useAsyncCallback:

Live demo

import React from "react";
import {useState} from "react";
import {useAsyncEffect} from "use-async-effect2";
import cpFetch from "cp-fetch";

function FetchComponent(props) {
    const [text, setText] = useState("");

    const cancel= useAsyncEffect(function* () {
            setText("fetching..."); 
            const response = yield cpFetch(props.url); // will throw a CanceledError if component get unmounted
            const json = yield response.json();
            setText(`Success: ${JSON.stringify(json)}`);
    }, [props.url]);

    return (
      <div>
      <span>{text}</span>
      <button onClick={cancel}>Cancel request</button>
      </div>
    );
}

Why ❓

You may run into a problem when you need to cancel some long-term asynchronous operation before it will be completed with success or failure, just because the result has lost its relevance to you.

Features

  • no dependencies (except [native] Promise)
  • built-in AbortController class
  • browser support
  • supports two ways to make your promise internal code cancellable:
    • onCancel callbacks (clear timers, abort requests)
    • signal provided by the AbortController (to wrap API like fetch method)
  • 🔥 supports cancellation of the whole chain
  • 🔥 supports generator to CPromise resolving (something similar like co library does);
  • 🔥 progress capturing support
  • 🔥 pretty awesome isomorphic decorators, with both specification support
  • CPromise.all supports concurrency limit
  • CPromise.all and CPromise.race methods have cancellation support, so the others nested pending promises will be canceled when the resulting promise settled
  • promise suspending (using pause and resume methods)
  • custom signals (emitSignal)
  • delay method to return a promise that will be resolved with the value after a timeout
  • ability to set the weight for each promise in the chain to manage the impact on chain progress
  • ability to attach meta info on each set of the progress
  • catch method supports error class filtering
  • Supports listening to multiple AbortController signals

Installation 🔨

  • Install for node.js using npm/yarn:
$ npm install c-promise2
$ yarn add c-promise2

The package consists of pre-built umd, cjs, mjs bundles which can be found in the ./dist/ directory

  • Import the library:
import {CPromise} from "c-promise2";
// const {CPromise} = require("c-promise2"); // using require
// import {CPromise} from "c-promise2/dev"; // development version
    
const chain= CPromise.delay(1000, 'It works!').then(message => console.log('Done', message));

//chain.cancel();

As an alternative you can use any CDN with npm support:

Comparison table

CPromise BlueBird.js p-cancelable
.cancel() is synchronous ❌* (.cancel emits a cancel signal synchronously, but the cancellation is asynchronous)
No setup code required to make cancellation work
Cancellation type asynchronous, rejection with CanceledError follows the special algorithm synchronous (ignoring attached callbacks) synchronous (ignoring attached callbacks) / asynchronous (rejecting)
onCancel handler to clean up internal tasks
Atomic sub-chains (protected from cancellation by upper chains)
Cancellation flows
Custom cancellation reasons
Cancellation composes with other own features, like .all, .race, .allSettled
Chaining/nested promise cancellation support
Generators support for “flat” coroutines (as a functional replacement for ECMA async functions)
Coroutines cancellation
Concurrency limitation
Signals/data flows
Chain progress capturing
Pause/resume support
timeouts
AbortController support (outer/inner) ✓/✓
.catch errors filter
.delay helper
ECMA decorators for methods (legacy/current) ✓/✓
Inherited from the native Promise

Examples

Progress capturing and cancellation

Basic example (Live demo):

import CPromise from 'c-promise';

const delay= (ms, value)=>{
  return new CPromise((resolve, reject, {onCancel}) => {
      const timer = setTimeout(resolve, ms, value);
      onCancel(() => {
          clearTimeout(timer);
          console.log('clear timeout');
      }) // clear internal operations on 'cancel' event
  })
}

const promise = CPromise.all([
  delay(1000, 'a'),
  delay(2000, 'b'),
  delay(3000, 'c'),
  delay(4000, 'd'),
  delay(5000, 'e'),
])
  .progress(value=> console.log(`Progress: ${(value * 100).toFixed(1)}%`));

console.log('isPromise:', promise instanceof Promise); // true

(async()=>{
 try {
     console.log(`Done: `, await promise);
 }catch(err){
     console.warn(`Failed: ${err}`);
     console.log('isCanceled:', promise.isCanceled);
 }
})()

setTimeout(()=> promise.cancel(), 3100); // cancel the promise after 3100ms

Console output:

isPromise: true
Progress: 20.0%
Progress: 40.0%
Progress: 60.0%
clear timeout
clear timeout
isCanceled: true
Failed: CanceledError: canceled

Process finished with exit code 0

Pause / resume promises

See the live demo

import CPromise from 'c-promise';

function cancelableDelay(ms, value){
    return new CPromise(function(resolve, reject, {onCancel, onPause, onResume}){
        let timestamp= Date.now();
        let timeLeft;
        let timer= setTimeout(resolve, ms, value);
        onPause(()=>{
            console.log(`Pause`);
            clearTimeout(timer);
            timer=0;
            timeLeft= ms - (Date.now()- timestamp);
            timestamp= Date.now();
        });

        onResume(()=>{
            console.log(`Resume`);
            timer= setTimeout(resolve, timeLeft, value);
        });

        onCancel(()=>{
            console.log(`Cancel`);
            timer && clearTimeout(timer);
        })
    });
}

const chain= cancelableDelay(1000, 123)
    .then(
        value=> console.log(`Done:`, value),
        err=> console.warn(`Fail: ${err}`)
    );

setTimeout(()=>{
    chain.pause();

    setTimeout(()=>{
        chain.resume();
    }, 5000);
}, 100);

Abortable fetch with timeout

This is how an abortable fetch (live example) with a timeout might look like

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

You can use the cp-fetch package which provides a ready to use CPromise wrapper for cross-platform fetch API.

Demo

Wrapping axios request

function cancelableAxios(url){
    return new CPromise((resolve, reject, {onCancel})=>{
        axios.get(url, {
            cancelToken: new axios.CancelToken(function executor(cancel) {
                onCancel(cancel)
            })
        }).then(resolve, reject);
    });
}

Tip: You can use ready for use cp-axios package for this.

Concurrency limitation:

import CPromise from "c-promise2";
import cpFetch from "cp-fetch";

(async()=>{
    await CPromise.all([
        'url1',
        'url2',
        'url3',
        'url4',
        'url5',
        'url6',
    ], {
        mapper: async (url) => {
            return cpFetch(url);
        },
        concurrency: 2
    })
    console.log('Done');
});

// Or

(async()=>{
    await CPromise.all(function*(){
        const urls= [
           'url1',
           'url2',
           'url3',
           'url4',
           'url5',
           'url6',
        ];
        for(let url of urls){
            yield cpFetch('url1');
        }
    }, {
        concurrency: 2
    })
    console.log('Done');
})();

Retrying async operations

Use CPromise.retry to retry async operations (3 attempts by default) with a delay(by default delay = attempt * 1000ms)

Live demo

const p= CPromise.retry(function*(scope, attempt){
  console.log(`attempt [${attempt}]`);
  this.innerWeight(3);
  yield CPromise.delay(1000);
  yield CPromise.delay(1000);
  yield CPromise.delay(1000);
  throw Error('oops');
}).progress((v) => {
  console.log(`Progress: ${v}`);
});

// setTimeout(() => p.cancel(), 5000); stop trying

Live demo

const p= CPromise.retry(async function(attempt){
  console.log(`attempt [${attempt}]`);
  await CPromise.delay(1000);
  await CPromise.delay(1000);
  await CPromise.delay(1000);
  throw Error('oops');
}).progress((v) => {
  console.log(`Progress: ${v}`);
});

You can use .cancel / .pause / .resume to control the sequence of attempts.

Using with React

React class components with CPromise decorators

With CPromise decorators, a generic React class component that fetches JSON might look like the following:

Live Demo

import React, { Component } from "react";
import {
  CPromise,
  CanceledError,
  ReactComponent,
  E_REASON_UNMOUNTED,
  listen,
  cancel
} from "c-promise2";
import cpAxios from "cp-axios";

@ReactComponent
class TestComponent extends Component {
  state = {
    text: ""
  };

  *componentDidMount(scope) {
    console.log("mount", scope);
    scope.onCancel((err) => console.log(`Cancel: ${err}`));
    yield CPromise.delay(3000);
  }

  @listen
  *fetch() {
    this.setState({ text: "fetching..." });
    try {
      const response = yield cpAxios(this.props.url).timeout(
        this.props.timeout
      );
      this.setState({ text: JSON.stringify(response.data, null, 2) });
    } catch (err) {
      CanceledError.rethrow(err, E_REASON_UNMOUNTED);
      this.setState({ text: err.toString() });
    }
  }

  *componentWillUnmount() {
    console.log("unmount");
  }

  render() {
    return (
      <div className="component">
        <div className="caption">useAsyncEffect demo:</div>
        <div>{this.state.text}</div>
        <button
          className="btn btn-success"
          type="submit"
          onClick={() => this.fetch(Math.round(Math.random() * 200))}
        >
          Fetch random character info
        </button>
        <button
          className="btn btn-warning"
          onClick={() => cancel.call(this, "oops!")}
        >
          Cancel request
        </button>
      </div>
    );
  }
}

Using some specific decorators we can control our async flow in a declarative way: Live Demo

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import "./styles.css";
import { async, listen, cancel, timeout } from "c-promise2";
import cpFetch from "cp-fetch";

export class TestComponent extends React.Component {
  state = {
    text: ""
  };

  @timeout(5000)
  @listen
  @async
  *componentDidMount() {
    console.log("mounted");
    const response = yield cpFetch(this.props.url);
    this.setState({ text: `json: ${yield response.text()}` });
  }

  render() {
    return <div>{this.state.text}</div>;
  }

  @cancel()
  componentWillUnmount() {
    console.log("unmounted");
  }
}

It automatically manages async code i.g request, so it protects from warning appearing like:

Warning: Can’t perform a React state update on an unmounted component.

React functional components

To use CPromise powers in functional components use use-async-effect2 hooks

Signals handling

Every CPromise instance can handle "signals", emitted using emitSignal method. The method emits a signal event on each pending promise in the chain until some handler returns true as the result. This method is used internally for predefined system signals for cancellation and suspending actions.

Live demo

const CPromise= require('../lib/c-promise');

const chain= new CPromise((resolve, reject, scope)=>{
    scope.on('signal', (type, data) => {
        if (type === 'inc') { // ignore other signal types
            console.log(`Signal ${type} handled`);
            resolve(data.x + 1);
            return true; // we have accepted this signal, so we should return `true` to stop the propagation
        }
    });
}).then(
    (value)=> console.log(`Done: ${value}`),
    (err)=> console.log(`Failed: ${err}`)
)

setTimeout(() => {
    // returns true
    console.log(`Inc signal result: ${chain.emitSignal('inc', {x: 2})}`);
    // returns false because there are no handlers to catch this signal type
    console.log(`Custom signal result: ${chain.emitSignal('custom')}`); 
});

Console output:

Signal inc handled
Inc signal result: true
Custom signal result: false
Done: 3

Process finished with exit code 0

There are the following system signals (just for reference, don't use them unless you know what you are doing):

  • CPromise.SIGNAL_CANCEL
  • CPromise.SIGNAL_PAUSE
  • CPromise.SIGNAL_RESUME

Using Generators as an alternative of ECMA async functions

Generally, you able to use CPromise with ES6 async functions, but if you need some specific functionality such as progress capturing or cancellation, you need to use generators instead of async functions to make it work. This is because the async function leads all the nested thenables into its own Promise class, and there is nothing we can do about it. Generators allow you to write asynchronous code just in the same way as async functions do, just use yield instead of await. See the live demo

import CPromise from "c-promise2";

const promise= CPromise.from(function*(){
    this.innerWeight(12); //optionally set the expected internal progress score of the nested chain
    yield CPromise.delay(1000);
    yield [CPromise.delay(1000), CPromise.delay(1500)] // resolve chains using CPromise.all([...chains]);
    yield [[CPromise.delay(1000), CPromise.delay(1500)]] // resolve chains using CPromise.race([...chains]);
    yield new Promise.resolve(); // any thenable object will be resolved 
    return "It works!";
})
.progress(value=> console.log(`Progress: ${value}`))
.then(message=> console.log(`Done: ${message}`));

Then method also supports generators as callback function

CPromise.resolve().then(function*(){
    const value1= yield CPromise.delay(3000, 3);
    // Run promises in parallel using CPromise.all (shortcut syntax)
    const [value2, value3]= yield [CPromise.delay(3000, 4), CPromise.delay(3000, 5)]
    return value1 + value2 + value3;
}).then(value=>{
    console.log(`Done: ${value}`); // Done: 12
}, err=>{
    console.log(`Failed: ${err}`);
})

Atomic sub-chains

Sometimes you need to prevent any sub-chain from being canceled from the outside because you want to allow some already started asynchronous procedure to be completed before closing the following promise chains. To solve this challenge use .atomic(["disabled"|"detached"|"await"]) method.

  • 'detached' - keep the sub-chain execution running in 'background', the main chain reject immediately
  • 'await' - wait for the sub-chain to complete and then reject the next promise in the outer chain
  • false considering as 'disabled'
  • true considering as 'await'

Check out the difference with examples: Normal cancellation behaviour .atomic('disabled') (Demo):

const p = CPromise.delay(1000, 1)
  .then((v) => {
    console.log("p1");
    return CPromise.delay(1000, 2);
  })
  .then((v) => {
    console.log("p2");
    return CPromise.delay(1000, 3);
  })
  .atomic()
  .then((v) => {
    console.log("p3");
    return CPromise.delay(1000, 4);
  })
  .then(
    (value) => console.log(`Done:`, value),
    (err) => console.warn(`Fail: ${err}`)
  );

setTimeout(() => p.cancel(), 1500);

output:

p1
Fail: CanceledError: canceled

Process finished with exit code 0

.atomic('detached') cancellation behaviour (Demo):

const p = CPromise.delay(1000, 1)
  .then((v) => {
    console.log("p1");
    return CPromise.delay(1000, 2);
  })
  .then((v) => {
    console.log("p2");
    return CPromise.delay(1000, 3);
  })
  .atomic('detached')
  .then((v) => {
    console.log("p3");
    return CPromise.delay(1000, 4);
  })
  .then(
    (value) => console.log(`Done:`, value),
    (err) => console.warn(`Fail: ${err}`)
  );

setTimeout(() => p.cancel(), 1500);

output:

p1
Fail: CanceledError: canceled
p2

.atomic('await') cancellation behaviour (Demo):

const p = CPromise.delay(1000, 1)
  .then((v) => {
    console.log("p1");
    return CPromise.delay(1000, 2);
  })
  .then((v) => {
    console.log("p2");
    return CPromise.delay(1000, 3);
  })
  .atomic()
  .then((v) => {
    console.log("p3");
    return CPromise.delay(1000, 4);
  })
  .then(
    (value) => console.log(`Done:`, value),
    (err) => console.warn(`Fail: ${err}`)
  );

setTimeout(() => p.cancel(), 1500);

output:

p1
p2
Fail: CanceledError: canceled

Process finished with exit code 0

Using decorators

The library supports a few types of decorators to make your code cleaner. All decorators are isomorphic- @async and @async() are totally equal. Also, they support both current and legacy decorator's specification.

ReactComponent([{subscribeAll?: boolean, bindListeners?: boolean, bindMethods?:boolean}])

Decorates class as React component:

  • decorates all generator to CPromise async function;
  • subscribes componentDidMount method to the internal AbortController signal of the class
  • decorates componentWillUnmount with @cancel decorator to invoke AbortController.abort() before running the method;
  • performs lazy event listeners binding (activated by default with bindListeners option). All user methods, whose name staring with on[A-Z] considering as event listeners.
  • performs lazy user methods binding (activated by default with bindMethods option).

options

  • subscribeAll - subscribe all async instance methods to the internal abort controller. By default, only componentDidMount will subscribe to the controller.
  • bindListeners - activates lazy binding for all listeners methods, whose name staring with on[A-Z] considering as event listeners.
  • bindMethods - activates lazy binding for all non-listeners methods.

@async([{timeout?: Number, innerWeight?: Number, label? : String, weight?: Number}])

Wraps a generator function into an async function, that returns CPromise instance.

import CPromise from 'c-promise2';
const {async}= CPromise;

class Test{
    @async
    *asyncMethod(x, y){
        const z= yield CPromise.delay(1000);
        return x + y + z;
    }  
}

const test= new Test();

const promise= test.asyncMethod(1, 2);

console.log(promise instanceof CPromise); // true

promise.then(value=> console.log(`Done: ${value}`), err=> console.warn(`Fail: ${err}`));

setTimeout(()=> promise.cancel(), 500);

@listen([signal: AbortSignal|String|Symbol])

Subscribe the CPromise async function to the AbortController signal. If the first argument is String or Symbol it will be considered as controller id, created internally in context of the class. If this argument not specified or null, the internal default AbortController will be used.

@cancel([reason: String], [signal: AbortSignal|String|Symbol])

Emits the cancel signal before the target function invoking. It can be called as a function, passing the context using .call or .apply.

import cpFetch from "cpFetch";

class Test{
    constructor(url) {
        this.fetchJSON(url).then(json=>{
            this.json= json;
            // working with json;
        })
    }

    @timeout(10000)
    @listen
    @async
    *fetchJSON(url){
        const response= yield cpFetch(url);
        return yield response.json();
    }  
    
    @cancel(E_REASON_DISPOSED)
    destroy(){
        // your code here
    }
}

@canceled([onRejected(err, scope, context): Function])

Catches rejections with CanceledError errors

class Klass{
   @canceled(()=> console.log(`canceled`))
   @listen('internalControllerId')
   *bar(){
     yield CPromise.delay(1000);
     console.log('done!');
   }

   @cancel('E_SOME_REASON', 'internalControllerId')
   *baz(){
   
   }
}
const instance= new Klass;

instance.bar().then(console.log, console.warn);

// cancel bar execution
cancel.call(intance, E_SOME_REASON, 'internalControllerId');
// calling `baz` will terminate the `bar` execution as well
instance.baz();

@progress(handler: Function)

Adds a listener to monitor the function progress

class Test{
    @progress(function (value, scope, data, context) {
        console.log(`Progress: ${value}`);
        // Prints: 0.25, 0.5, 0.75, 1
    })
    @innerWeight(4)
    @async
    * asyncMethod() {
        yield delay(100);
        yield delay(100);
        yield delay(100);
        yield delay(100);
    }
}

const test= new Test();
const promise= test.asyncMethod();

@timeout(ms: Number)

Sets the timeout option for the CPromise async function.

@innerWeight(weight: Number)

Sets the innerWeight option for the CPromise async function.

@label(label: String)

Sets the label option for the CPromise async function.

@done([doneHandler(value, isRejected, scope, context)])

Decorates async function with done chain

@atomic([atomicType: 'disabled'|'detached'|'await'|true|false])

Configures decorated CPromise async function as atomic.

Events

All events (system and user defined) can be fired only when promises in pending state.

Predefined (system) events:

  • cancel(reason: CanceledError) - fires when promise is canceled (rejected with CanceledError)
  • pause - on promise pause request
  • resume - on promise resume request
  • capture(scope: CPromise) - fired when some consumer directly or above standing in the chain starts progress capturing
  • progress(value: Number, scope: CPromise, data: Object?) - fired when promise chain progress changes

Event listener attaching shortcuts (methods bound to the promise instance):

  • onCancel(listener: Function)
  • onPause(listener: Function)
  • onResume(listener: Function)
  • onCapture(listener: Function)

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.

  • cp-axios - a simple axios wrapper that provides an advanced cancellation api
  • cp-fetch - fetch with timeouts and request cancellation
  • use-async-effect2 - cancel async code in functional React components

API Reference

Cancellable Promise with extra features

CPromise.CanceledError : CanceledError

CanceledError class

Kind: static property of CPromise

CPromise.AbortController : AbortController | AbortControllerEx

Refers to the AbortController class (native if available)

Kind: static property of CPromise

CPromise.AbortControllerEx : AbortControllerEx

AbortControllerEx class

Kind: static property of CPromise

CPromise.E_REASON_CANCELED

Generic cancellation reason

Kind: static property of CPromise

CPromise.E_REASON_DISPOSED

Cancellation reason for the case when the instance will be disposed

Kind: static property of CPromise

CPromise.E_REASON_TIMEOUT

Timeout cancellation reason

Kind: static property of CPromise

CPromise.E_REASON_UNMOUNTED

React specific canceled reason

Kind: static property of CPromise

CPromise.async : function

async decorator

Kind: static property of CPromise

CPromise.listen : function

listen decorator

Kind: static property of CPromise

CPromise.cancel : function

cancel decorator

Kind: static property of CPromise

CPromise.ReactComponent : function

cancel decorator

Kind: static property of CPromise

CPromise.atomic : function

make CPromise function atomic

Kind: static property of CPromise

CPromise.done : function

append done chain to the resulting promise of the decorated method

Kind: static property of CPromise

CPromise.timeout : function

timeout decorator

Kind: static property of CPromise

CPromise.innerWeight : function

innerWeight decorator

Kind: static property of CPromise

CPromise.label : function

label decorator

Kind: static property of CPromise

CPromise.canceled : function

label decorator

Kind: static property of CPromise

CPromise.progress : function

progress decorator

Kind: static property of CPromise

CPromise.promisify : function

Kind: static property of CPromise

CPromise~CPromise : object

Creates a new CPromise instance

Kind: inner namespace of CPromise
Extends: Promise

Param Type Description
[executor] CPromiseExecutorFn promise executor function that will be invoked in the context of the new CPromise instance
[options] CPromiseOptions

cPromise.signal : AbortSignal

get promise abort signal object

Kind: instance property of CPromise

cPromise.isPending ⇒ Boolean

indicates if the promise is pending

Kind: instance property of CPromise

cPromise.isCanceled ⇒ Boolean

indicates if the promise is pending

Kind: instance property of CPromise

cPromise.isCaptured ⇒ Boolean

indicates if the promise progress is captured

Kind: instance property of CPromise

cPromise.isPaused ⇒ Boolean

indicates if the promise is paused

Kind: instance property of CPromise

cPromise.isRejected ⇒ Boolean

indicates if the promise is rejected

Kind: instance property of CPromise

cPromise.parent ⇒ CPromise | null

get parent promise

Kind: instance property of CPromise

cPromise.onCancel(listener) ⇒ CPromise

registers the listener for cancel event

Kind: instance method of CPromise

Param Type
listener OnCancelListener

cPromise.onPause(listener) ⇒ CPromise

registers the listener for pause event

Kind: instance method of CPromise

Param Type
listener OnPauseListener

cPromise.onResume(listener) ⇒ CPromise

registers the listener for resume event

Kind: instance method of CPromise

Param Type
listener OnResumeListener

cPromise.onCapture(listener) ⇒ CPromise

registers the listener for capture event

Kind: instance method of CPromise

Param Type
listener OnCaptureListener

cPromise.onDone(listener)

registers the listener for done event

Kind: instance method of CPromise

Param Type
listener CPDoneListener

cPromise.onSignal(listener)

registers the listener for done event

Kind: instance method of CPromise

Param Type
listener CPSignalListener

cPromise.totalWeight([weight]) ⇒ Number | CPromise

Set or get the total weight of the inner chains

Kind: instance method of CPromise

Param Type
[weight] Number

cPromise.innerWeight([weight]) ⇒ Number | CPromise

Set or get the total weight of the inner chains

Kind: instance method of CPromise

Param Type
[weight] Number

cPromise.progress([value], [data], [scope]) ⇒ Number | CPromise

Set promise progress

Kind: instance method of CPromise

Param Type Description
[value] Number a number between [0, 1]
[data] * any data to send for progress event listeners
[scope] CPromise CPromise scope

cPromise.propagate(type, data, [scope]) ⇒ CPromise

emit propagate event that will propagate through each promise scope in the chain (bubbling)

Kind: instance method of CPromise

Param Type Default Description
type String | symbol some type to identify the data kind
data * some data
[scope] CPromise CPromise scope

cPromise.captureProgress([options]) ⇒ CPromise

capture initial progress state of the chain

Kind: instance method of CPromise

Param Type Description
[options] Object
options.throttle Number set min interval for firing progress event
options.innerWeight Number set weight of the nested promises

cPromise.scopes([pendingOnly]) ⇒ Array.<CPromise>

Returns all parent scopes that are in pending state

Kind: instance method of CPromise

Param Type Default
[pendingOnly] boolean false

cPromise.timeout([ms]) ⇒ Number | CPromise

timeout before the promise will be canceled

Kind: instance method of CPromise

Param Type Description
[ms] Number timeout in ms

cPromise.weight([weight]) ⇒ Number | CPromise

Sets the promise weight in progress capturing process

Kind: instance method of CPromise
Returns: Number | CPromise - returns weight if no arguments were specified

Param Type Description
[weight] Number any number greater or equal 0

cPromise.label([label]) ⇒ Number | CPromise

Sets the promise label

Kind: instance method of CPromise
Returns: Number | CPromise - returns weight if no arguments were specified

Param Type Description
[label] String any string

cPromise.resolve(value) ⇒ CPromise

Resolves the promise with given value

Kind: instance method of CPromise

Param
value

cPromise.reject(err) ⇒ CPromise

Rejects the promise with given error

Kind: instance method of CPromise

Param
err

cPromise.pause() ⇒ Boolean

Pause promise

Kind: instance method of CPromise

cPromise.resume() ⇒ Boolean

Resume promise

Kind: instance method of CPromise

cPromise.atomic([type]) ⇒

Make promise chain atomic (non-cancellable for external signals)

Kind: instance method of CPromise
Returns: CPromise

Param Type
[type] AtomicType

cPromise.cancel([reason], [forced])

throws the CanceledError that cause promise chain cancellation

Kind: instance method of CPromise

Param Type Default
[reason] String | Error
[forced] Boolean false

cPromise.emitSignal(type, [data], [handler], [locator]) ⇒ Boolean

Emit a signal of the specific type

Kind: instance method of CPromise

Param Type
type Signal
[data] *
[handler] SignalHandler
[locator] SignalLocator

cPromise.delay(ms) ⇒ CPromise

Returns a chain that will be resolved after specified timeout

Kind: instance method of CPromise

Param Type
ms Number

cPromise.aggregate([weight]) ⇒ CPromise

Aggregate promise chain into one promise

Kind: instance method of CPromise

Param Type Default
[weight] number 1

cPromise.then(onFulfilled, [onRejected]) ⇒ CPromise

returns a CPromise. It takes up to two arguments: callback functions for the success and failure cases of the Promise.

Kind: instance method of CPromise

Param Type
onFulfilled onFulfilled
[onRejected] onRejected

cPromise.catch(onRejected, [filter]) ⇒ CPromise

Catches rejection with optionally specified Error class

Kind: instance method of CPromise

Param Type
onRejected function
[filter] Error

cPromise.finally(onFinally) ⇒ Promise.<(T|void)>

Add handler that will be invoked when promise settled

Kind: instance method of CPromise

Param Type
onFinally CPFinallyHandler

cPromise.done(doneHandler) ⇒ CPromise

Add a handler that will be called after the promise has been fulfilled, but unlike finally, the returned plain value will not be ignored

Kind: instance method of CPromise

Param Type
doneHandler CPDoneHandler

cPromise.canceled([onCanceled]) ⇒ CPromise

Catches CancelError rejection

Kind: instance method of CPromise

Param Type
[onCanceled] function

cPromise.listen(signal) ⇒ CPromise

Listen for abort signal

Kind: instance method of CPromise

Param Type
signal AbortSignal

cPromise.on(type, listener, [prepend]) ⇒ CPromise

adds a new listener

Kind: instance method of CPromise

Param Type Default
type EventType
listener function
[prepend] Boolean false

cPromise.off(type, listener) ⇒ CPromise

removes the listener

Kind: instance method of CPromise

Param Type
type EventType
listener function

cPromise.listenersCount(type) ⇒ Number

returns listeners count of the specific event type

Kind: instance method of CPromise

Param Type
type EventType

cPromise.hasListeners(type) ⇒ Boolean

checks if there are listeners of a specific type

Kind: instance method of CPromise

Param Type
type String | Symbol

cPromise.once(type, listener) ⇒ CPromise

add 'once' listener

Kind: instance method of CPromise

Param Type
type EventType
listener function

cPromise.emit(type, ...args) ⇒ CPromise

emits the event

Kind: instance method of CPromise

Param Type
type EventType
...args

cPromise.emitHook(type, ...args) ⇒ Boolean

Emits event as a hook. If some listener return true, this method will immediately return true as the result. Else false will be retuned

Kind: instance method of CPromise

Param Type
type EventType
...args

cPromise.toString([entireChain]) ⇒ string

Render promise to String

Kind: instance method of CPromise

Param Type Default Description
[entireChain] boolean false render the entire promise chain

CPromise.version ⇒ string

CPromise version string

Kind: static property of CPromise

CPromise.versionNumber ⇒ number

CPromise version number

Kind: static property of CPromise

CPromise.isCanceledError(thing) ⇒ boolean

Checks if thing is an CanceledError instance

Kind: static method of CPromise

Param
thing

CPromise.delay(ms, value, [options]) ⇒ CPromise

Returns a CPromise that will be resolved after specified timeout

Kind: static method of CPromise

Param Type Default Description
ms Number delay before resolve the promise with specified value
value
[options] object
[options.progressTick] number 1000 progress timer tick, must be >= 100ms

CPromise.all(iterable, [options]) ⇒ CPromise

Returns a single CPromise that resolves to an array of the results of the input promises. If one fails then other promises will be canceled immediately

Kind: static method of CPromise

Param Type
iterable Iterable | Generator | GeneratorFunction | array
[options] CPAllOptions

Example

CPromise.all(function*(){
    yield axios.get(url1);
    yield axios.get(url2);
    yield axios.get(url3);
}, {concurrency: 1}).then(console.log)

CPromise.race(pending) ⇒ CPromise

returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise. Other pending promises will be canceled immediately

Kind: static method of CPromise

Param Type
pending Iterable

CPromise.allSettled(iterable, [options]) ⇒ CPromise

returns a promise that resolves after all of the given promises have either fulfilled or rejected

Kind: static method of CPromise

Param Type
iterable Iterable | Generator | GeneratorFunction
[options] CPAllOptions

CPromise.retry(fn, [options]) ⇒ CPromise

Retry async operation

Kind: static method of CPromise

Param Type
fn CPGeneratorRetryFunction | CPRetryFunction
[options] object
[options.args] array
[options.retries] number
[options.delayWeight] number | CPRetryDelayResolver
[options.delay] object

CPromise.resolve([thing], [options]) ⇒ CPromise

Converts thing to CPromise using the following rules:

  • CPromise instance returns as is
  • Objects with special method defined with key Symbol.for('toCPromise') will be converted using this method The result will be cached for future calls
  • Thenable wraps into a new CPromise instance, if thenable has the cancel method it will be used for canceling
  • Generator function will be resolved to CPromise
  • Array will be resoled via CPromise.all, arrays with one element (e.g. [[1000]]) will be resolved via CPromise.race

This method returns null if the conversion failed.

Kind: static method of CPromise

Param Type
[thing] *
[options] resolveOptionsObject | Boolean

CPromise.promisify(originalFn, [options]) ⇒ function

Converts callback styled function|GeneratorFn|AsyncFn to CPromise async function

Kind: static method of CPromise

Param Type
originalFn function | GeneratorFunction | AsyncFunction
[options] PromisifyOptions | function | Boolean

CPromise.run(generatorFn, [options]) ⇒ CPromise

Resolves the generator to an CPromise instance

Kind: static method of CPromise

Param Type Description
generatorFn GeneratorFunction
[options] Object
[options.args] Array
[options.resolveSignatures] Boolean resolve extra signatures (like arrays with CPromise.all)
[options.scopeArg] Boolean pass the CPromise scope as the first argument to the generator function
[options.context] *

CPromise.async([options])

Decorator to make CPromise async function from generator, ECMA async or callback-styled method

Kind: static method of CPromise

Param Type
[options] object
[options.timeout] number
[options.label] string
[options.innerWeight] number
[options.weight] number
[options.listen] AbortControllerId | AbortController | AbortSignal | Array.<(AbortControllerId|AbortController|AbortSignal)>
[options.atomic] AtomicType

CPromise.listen([signals])

Decorator to subscribe CPromise async method to the internal or external controller

Kind: static method of CPromise

Param Type
[signals] AbortControllerId | AbortController | AbortSignal | Array.<(AbortControllerId|AbortController|AbortSignal)>

CPromise.cancel([reason], signal)

Decorator to cancel internal or external abort controller before the decorated function invocation. Can be used as a plain function by passing a object context with .call or .apply methods

Kind: static method of CPromise

Param Type
[reason] string
signal AbortControllerId | AbortController

Example

el.onclick= ()=> cancel.call(this, reason, 'myControllerId'); - to use the decorator as a plain function

CPromise.canceled(onCanceledChain)

Decorator to add an onCanceled rejection handler to the resulting promise of the decorated method

Kind: static method of CPromise

Param Type
onCanceledChain function | GeneratorFunction

CPromise.progress(onProgressHandler)

Decorator to subscribe the handler to the onProgress event of the resulting promise

Kind: static method of CPromise

Param Type
onProgressHandler ProgressDecoratorHandler

CPromise.ReactComponent(options)

Decorate class as React component

Kind: static method of CPromise

Param Type
options boolean | ReactComponentDecoratorOptions

CPromise.timeout(ms)

Decorator to set timeout for the resulting promise of the decorated function

Kind: static method of CPromise

Param Type
ms number

CPromise.label(str)

Decorator to set label for the resulting promise of the decorated function

Kind: static method of CPromise

Param Type
str string

CPromise.innerWeight(weight)

Decorator to set innerWeight for the resulting promise of the decorated function

Kind: static method of CPromise

Param Type
weight number

CPromise.atomic(atomicType)

Decorator to set timeout for the resulting promise of the decorated function

Kind: static method of CPromise

Param Type
atomicType AtomicType

CPromise.done(doneHandler)

append done chain to the resulting promise of the decorated method

Kind: static method of CPromise

Param Type
doneHandler CPDecoratorDoneHandler

CPromise.isPromisifiedFn(fn) ⇒ * | boolean

Returns promisification strategy that was used to the original function

Kind: static method of CPromise

Param Type
fn function

CPromise.isCPromise(thing, [anyVersion]) ⇒ boolean

Check whether object is CPromise instance

Kind: static method of CPromise

Param Type Default
thing *
[anyVersion] boolean false

CPromise~EventType : String | Symbol

Kind: inner typedef of CPromise

CPromise~CPromiseExecutorFn : function

Kind: inner typedef of CPromise
this: CPromise

Param Type
resolve function
reject function
scope CPromise

CPromise~PromiseOptionsObject : Object

Kind: inner typedef of CPromise
Properties

Name Type Default Description
label String
timeout Number
weight Number
[nativeController] Boolean false prefer native AbortController class as the internal signal

CPromise~CPromiseOptions : PromiseOptionsObject | String | Number

If value is a number it will be considered as the value for timeout option If value is a string it will be considered as a label

Kind: inner typedef of CPromise

CPromise~OnCancelListener : function

Kind: inner typedef of CPromise

Param Type
reason CanceledError

CPromise~OnPauseListener : function

Kind: inner typedef of CPromise

CPromise~OnResumeListener : function

Kind: inner typedef of CPromise

CPromise~OnCaptureListener : function

Kind: inner typedef of CPromise

Param Type
CPromise scope

CPromise~CPDoneListener ⇒ CPromise

Kind: inner typedef of CPromise

Param Type
value *
isRejected boolean

CPromise~CPSignalListener ⇒ Boolean

Kind: inner typedef of CPromise

Param Type
type Signal
data *

CPromise~AtomicType : number | boolean | "disabled" | "detached" | "await"

Kind: inner typedef of CPromise

CPromise~Signal : String | Symbol

Kind: inner typedef of CPromise

CPromise~SignalHandler ⇒ Boolean

Kind: inner typedef of CPromise
this: {CPromise}

Param Type
data *
type Signal
scope CPromise

CPromise~SignalLocator ⇒ Boolean

Kind: inner typedef of CPromise
this: {CPromise}

Param Type
data *
type Signal
scope CPromise
isRoot Boolean

CPromise~CPFinallyHandler : function

Kind: inner typedef of CPromise
this: CPromise

Param Type
settledValue *
isRejected boolean
scope CPromise

CPromise~CPDoneHandler : function

Kind: inner typedef of CPromise
this: CPromise

Param Type
settledValue *
isRejected boolean
scope CPromise

CPromise~CPAllOptions : object

Kind: inner typedef of CPromise
Properties

Name Type Description
[concurrency] number limit concurrency of promise being run simultaneously
[mapper] function function to map each element
[ignoreResults] boolean do not collect results
[signatures] boolean use advanced signatures for vales resolving

CPromise~CPRetryFunction ⇒ *

Kind: inner typedef of CPromise

Param Type
attempt number
args array

CPromise~CPGeneratorRetryFunction ⇒ *

Kind: inner typedef of CPromise

Param Type
scope CPromise
attempt number
args array

CPromise~CPRetryDelayResolver ⇒ number

Kind: inner typedef of CPromise
Returns: number - a delay in ms before next attempt

Param Type
attempt number
retries number

CPromise~resolveOptionsObject : Object

Kind: inner typedef of CPromise
Properties

Name Type Default
[resolveSignatures] Boolean true
[atomic] AtomicType true
[args] *

CPromise~PromisifyFinalizeFn : function

Kind: inner typedef of CPromise

Param Type
result *
scope CPromise

CPromise~CPPromisifyDecoratorFn ⇒ function

Kind: inner typedef of CPromise

Param Type Description
originalFn function function to decorate
options PromisifyOptions

CPromise~PromisifyOptions : Object

Kind: inner typedef of CPromise
Properties

Name Type Default Description
[multiArgs] Boolean aggregate all passed arguments to an array
[finalize] PromisifyFinalizeFn aggregate all passed arguments to an array
[fnType] "plain" | "generator" | "async"
[scopeArg] boolean pass the CPromise scope as the first argument to the generator function
[decorator] function CPPromisifyDecoratorFn
[alignArgs] boolean align passed arguments to function definition for callback-styled function
[once] boolean true don't promisify already promisified function
[types] array.<('plain'|'async'|'generator')> function types to promisify

CPromise~AbortControllerId : string | symbol

Kind: inner typedef of CPromise

CPromise~ProgressDecoratorHandler : function

Kind: inner typedef of CPromise

Param Type
progress number
scope CPromise
data *
context object

CPromise~ReactComponentDecoratorOptions : object

Kind: inner typedef of CPromise
Properties

Name Type Default
[subscribeAll] boolean false
[bindListeners] boolean true
[bindMethods] boolean true

CPromise~CPDecoratorDoneHandler : function

Kind: inner typedef of CPromise

Param Type
value *
isRejected boolean
scope CPromise
context object

License

The MIT License Copyright (c) 2020 Dmitriy Mozgovoy robotshara@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.