DEV Community

rohit raut
rohit raut

Posted on

How to cancel a promise in javascript ?

I know that promis in js. Are not cancellable but i know genius mind all around the globe must have found some way to make it possible?
comment your answers and let me know...

javascript #ecmascript #frontend

Top comments (5)

Collapse
 
digitalbrainjs profile image
Dmitriy Mozgovoy • Edited

Using 'c-promise2' package we can do the following trick:
(Live Demo - jsfiddle.net/DigitalBrain/c6njyrt9... )

import CPromise from "c-promise2";

function fetchWithTimeout(url, {timeout, ...fetchOptions}= {}) {
   return new CPromise((resolve, reject, {signal}) => {
      fetch(url, {...fetchOptions, signal}).then(resolve, reject)
   }, timeout)
}

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);  // cancel the pending chain when you need
// yes, the related network request will be canceled too

// CPromise.race([
//    fetchWithTimeout(url1), fetchWithTimeout(url2), fetchWithTimeout(url3)
// ]).then(console.log); 
// The other two slower network requests will be aborted as well
Enter fullscreen mode Exit fullscreen mode

Simple React Demo of using AbortController signal - codesandbox.io/s/react-fetch-class...

export class AsyncComponent extends React.Component {
    state = {};

    async componentDidMount() {
        console.log("mounted");
        this.controller = new CPromise.AbortController();
        try {
            await this.myAsyncTask1();
            const result= await this.myAsyncTask2();
            this.setState({ text: result });
        } catch (err) {
            if (CPromise.isCanceledError(err)) {
                console.log("tasks terminated");
                return;
            }
            throw err;
        }
    }

    myAsyncTask1() {
        return CPromise.from(function* () {
            yield ...
            yield ...
        }).listen(this.controller.signal);
    }

    myAsyncTask2() {
        return new CPromise((resolve, reject, { onCancel }) => {
            //code
        }).listen(this.controller.signal);
    }

    componentWillUnmount() {
        console.log("unmounted");
        this.controller.abort(); // kill all tasks
    }
}
Enter fullscreen mode Exit fullscreen mode

Simple React Demo using hooks - codesandbox.io/s/react-cpromise-fe...

import React, { useEffect, useState } from "react";
import CPromise from "c-promise2";
import cpFetch from "cp-fetch";

function MyComponent(props) {
    const [text, setText] = useState("fetching...");

    useEffect(() => {
        console.log("mount");
        const promise = cpFetch(props.url)
            .then((response) => response.json())
            .then((value) => CPromise.delay(1000, value)) //one more dummy task
            .then((json) => setText(`Success: ${JSON.stringify(json)}`))
            .canceled() // catch CanceledError
            .catch((err) => {
                setText(`Failed: ${err}`);
            });

        return () => {
            console.log("unmount");
            promise.cancel();
        };
    }, [props.url]);

    return <p>{text}</p>;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
akashkava profile image
Akash Kava

Promise cannot be cancelled, it is the process that returns promise must be cancellable.

For example, XmlHttpRequest is cancellable as it has an abort method.

Fetch api also supports AbortController.signal, that is cancellable.

As Promises are deeply nested, and promise is a result, it cannot be cancelled and even if somehow you ignore by putting timeout, underlying process will not be cancelled.

Collapse
 
wierdorohit123 profile image
rohit raut

Hi akash i know we cannot cancel the network call but can u tell me how to not perform the action which was suppose to be performed when promise would have resolved?

Collapse
 
alexparra profile image
Alex Parra

Think I’ve only seen cancel by timeout with Promise.race[mainPromise, timeoutPromise].
TimeoutPromise throws after a certain amount of time triggering the catch handler of race.

Collapse
 
mochfamir profile image
Mochamad Faishal Amir

I think to handle a cancellable request you can use RxJS