Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PromiseKit cancel a promise

How do I cancel a promise that has been neither fulfilled or rejected yet?

The documentation for PromiseKit talks about cancelling a promise, but I can't find a specific example of how to do this.

Given:

currentOperation = client.load(skip: skip, query: nil)
currentOperation!.then { (items) in
   self.processItems(items: items, skip: skip, query: query)
}.catch { (error) in
    print("failed to load items - just retrying")
    self.loadIfNeeded(skip: skip, query: query, onlyInStock: onlyInStock)
}

If the query changes (user enters some text in the search bar) I want to cancel and discard the currentOperation, starting a new promise.

like image 666
Jasper Blues Avatar asked May 11 '17 05:05

Jasper Blues


People also ask

How do you cancel a 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.

Can we cancel promises?

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 .


3 Answers

In order to cancel a promise you have to reject it with any error type that conforms to CancellableError protocol. This way any catch block with policy parameter set to allErrorsExceptCancellation will let the error pass through.

If you need a CancellablePromise you may subclass Promise and implement a cancel() function that will reject with a CancellableError when called. Here is a minimal implementation:

https://gist.github.com/EfraimB/918eebdf7dd020801c72da1289c8d797

UPDATE:

Here is an update for the new PromiseKit version (6.4.1)

https://gist.github.com/EfraimB/3ac240fc6e65aa8835df073f68fe32d9

like image 128
Efraim Avatar answered Oct 16 '22 20:10

Efraim


Maybe my library CancellablePromiseKit is useful for you: https://github.com/johannesd/CancellablePromiseKit

It allows you to define a CancellablePromise similarly to how you define an ordinary Promise, with the addition of a cancel block. In that block, you write the code for cancelling the underlying task. The promise can then be cancelled by calling cancellablePromise.cancel() from the outside.

let cancellablePromise = CancellablePromise<String> { resolver in
    let currentOperation = client.load(skip: skip, query: nil)
    currentOperation.completion = { (value, error) in
        resolver.resolve(value, error)
    }
    return {
        // The cancel block
        currentOperation.stop()
    }
}

The lib also overloads when and race to cancel tasks automatically.

like image 2
Johannes Dörr Avatar answered Oct 16 '22 19:10

Johannes Dörr


In PromiseKit 7, use func cancellize() to convert a Promise or Guarantee into a promise that can be cancelled:

currentOperation = client.load(skip: skip, query: nil)
let currentOperationCancellable = currentOperation!.then { (items) in
   self.processItems(items: items, skip: skip, query: query)
}.cancellize()
currentOperationCancellable.catch { (error) in
    print("failed to load items - just retrying")
    self.loadIfNeeded(skip: skip, query: query, onlyInStock: onlyInStock)
}

Use func cancel() or func cancel(with:) to cancel a cancellable Promise or Guarantee:

currentOperationCancellable.cancel()
currentOperationCancellable.cancel(with: NSError(domain: "", code: 0, userInfo: nil))
like image 1
Roman Podymov Avatar answered Oct 16 '22 20:10

Roman Podymov