Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to add a cancel method to Promise in Typescript?

Tags:

typescript

I'd like to create a QueryPromise that is just a concrete promise with a cancel method. Here's how it would be used:

function runQuery(text: string): QueryPromise {
  return new QueryPromise((resolve,reject) => {nativeQuery(resolve)})
}

Here is my first attempt, hopefully pretty understandable:

interface CancellablePromise<T> extends Promise<T> {
  cancel: () => void
}

// create the promise my app will use
type QueryPromise = CancellablePromise<string|boolean>

But that's not sufficient.

After a few hours of trial and error I managed to get close, but this seems tedious and anything but DRY.

interface CancellablePromise<T> extends Promise<T> {
  cancel: () => void
}
// also need this interface so the variable can be declared
// plus need to redeclare methods to return the new type
interface CancellablePromiseConstructor extends PromiseConstructor {
  new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): CancellablePromise<T>;
  cancel: () => void
}

type QueryPromise = CancellablePromise<string|boolean>    // for parameter types
var QueryPromise: CancellablePromiseConstructor = Promise // for the new operator

// some example code to exercise the promise
function runQuery(text: string): QueryPromise {
  return new QueryPromise((resolve,reject) => {nativeQuery(resolve)})
}

I feel like I've gone a long way down the wrong road... Does anyone know of a better way to do this?

like image 448
bronson Avatar asked Sep 28 '17 05:09

bronson


People also ask

Is it possible to cancel a promise?

Promises have settled (hah) and it appears like it will never be possible to cancel a (pending) promise. Instead, there is a cross-platform (Node, Browsers etc) cancellation primitive as part of WHATWG (a standards body that also builds HTML) called AbortController .

How do I interrupt promises?

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.

How do I cancel pending promise?

To force cancel a promise with JavaScript, we use the AbortController constructor. const controller = new AbortController(); const task = new Promise((resolve, reject) => { //... controller. signal.


1 Answers

TypeScript interfaces and types describe contracts. Yours are fine:

interface CancellablePromise<T> extends Promise<T> {
  cancel: () => void
}

type QueryPromise = CancellablePromise<string | boolean>

You can then implement a contract as you want. Here is an example:

function runQuery(text: string): QueryPromise {
  let rejectCb: (err: Error) => void
  let p: Partial<QueryPromise> = new Promise<string | boolean>((resolve, reject) => {
    rejectCb = reject
    /* ... Here the implementation of the query ... */
  });
  p.cancel = () => {
    /* ... Here the implementation of the aborting ... */
    rejectCb(new Error("Canceled"))
  }
  return p as QueryPromise
}

Notices:

  • The implementation of cancel should reject the promise;
  • I use Partial<QueryPromise> in order to add the member cancel afterward.
like image 51
Paleo Avatar answered Sep 21 '22 05:09

Paleo