Extending native JavaScript Promise with cancellation support Updated, below is a more current and simple version of this. Also, if you track the progress of TC39's &quot;ECMAScript Cancellation&quot; proposal, this thread might be worth checking out.

I'm playing with Promise Extensions for JavaScript (prex) library and I like it a lot. Amongst other things, this library appears to be a prototype behind the current ECMA TC39 proposal for cancellation and it uses the familiar cancellation token approach, popularized by .NET Task API.
I want to extend the standard Promise class with cancellation support, similar to how it is implemented in Bluebird (i.e., with an optional oncancel callback) but using prex.CancellationToken.
Here is a draft that can be run with NodeJS:
const prex = require('prex');

class CancellablePromise extends Promise {
  constructor(executor, token) {
    if (!token) {
      // if no token supplied, just delegate to the parent class
      super(executor);
      return;
    }
    
    const observeCancellation = async () =&gt; {
      // prex.Deferred is similar to TaskCompletionSource in .NET
      const deferred = new prex.Deferred();

      executor(
        deferred.resolve, 
        deferred.reject, 
        cancelListener =&gt; 
          deferred.cancelListener = cancelListener);  

      const registration = token.register(() =&gt; {
        try {
          // capture the CancelError
          token.throwIfCancellationRequested();
        }
        catch (cancelError) {
          try {
            // the token cancellation callback is synchronous,
            // and so is the executor-provided cancelListener callback
            deferred.cancelListener &amp;&amp; deferred.cancelListener(cancelError);
            // reject here if cancelListener has not resolved/rejected it
            deferred.reject(cancelError);
          }
          catch (error) {
            // in case cancelListener throws
            deferred.reject(error);
          }
        }
      });
    
      try {
        return await deferred.promise;
      }
      finally {
        registration.unregister();
      }
    };

    super((resolve, reject) =&gt; 
      observeCancellation().then(resolve, reject));
  }
}

// delayWithCancellation
function delayWithCancellation(timeoutMs, token) {
  console.log(`delayWithCancellation: ${timeoutMs}`);

  return new CancellablePromise((resolve, reject, setCancelListener) =&gt; {
    token.throwIfCancellationRequested();
    const id = setTimeout(resolve, timeoutMs);
    setCancelListener(e =&gt; clearTimeout(id));
  }, token);
}

// main
async function main() {
  const tokenSource = new prex.CancellationTokenSource();
  setTimeout(() =&gt; tokenSource.cancel(), 2000); // cancel after 1500ms

  const token = tokenSource.token;

  await delayWithCancellation(1000, token);
  console.log(&quot;successfully delayed.&quot;); // we should reach here

  await delayWithCancellation(1500, token);
  console.log(&quot;successfully delayed.&quot;); // we should not reach here
}

main().catch(error =&gt; console.log(error));
You can override the executor and can pass an onCancel function to it like following:
class ResponsePromise extends Promise {
  constructor(executor) {
    const onCancel =  (cb) =&gt; {
      //using nextTick because we cant use &quot;this&quot; before super()
      setTimeout(()=&gt; {
        this.cancelCb = cb;
      })
    }

    const oExecutor = (resolve, reject) =&gt; {
      executor(resolve, reject, onCancel);
    }

    super(oExecutor);
  }
  cancel() {
    if (this.cancelCb) {
      this.cancelCb();
    } else {
      console.warn('onCancel not provided');
    }
  }

I have explained this in http://w3.cafe/promise-with-progress-javascript/