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.
To force cancel a promise with JavaScript, we use the AbortController constructor. const controller = new AbortController(); const task = new Promise((resolve, reject) => { //... controller. signal.
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 .
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
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.
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))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With