PromiseKit with Swift: terminate chain of promises

6.1k views Asked by At

I'm trying to use PromiseKit with Swift. I am not really familiar with it, and there doesn't seem to be much information on its usage with Swift.

I can't seem to figure out how to terminate a chain of promises. As long as the last (terminal) then block contains a single statement, everything is fine:

firstly {
    // ...
}.then { obj in
    self.handleResult(obj)
}.catch { error in
    self.handleError(error)
}

However, if I try to add another statement, compiler complains:

firstly {
    // ...
}.then { obj in
    self.handleResult(obj)
    self.doSomethingDifferent(obj)
}.catch { error in // compiler error: Missing return in a closure expected to return 'AnyPromise'
    self.handleError(error)
}

Obviously, the solution is to return another promise, but it doesn't make sense in the terminal block. Is there anything else I can do?

4

There are 4 answers

1
Soheil Jadidian On BEST ANSWER

According to http://promisekit.org/PromiseKit-2.0-Released/, under Swift Compiler Issues section:

The Swift compiler will often error with then. To figure out the issue, first try specifying the full signature for your closures:

foo.then { x in
    doh()
    return bar()
}

// will need to be written as:

foo.then { obj -> Promise<Type> in
    doh()
    return bar()
}

// Because the Swift compiler cannot infer closure types very
// well yet. We hope this will be fixed.

// Watch out for  one-line closures though! Swift will
// automatically infer the types, which may confuse you:

foo.then {
    return bar()
}

So you'll have to change your code to:

firstly {
    // ...
}.then { obj -> Promise<WhateverTypeDoSomethingDifferentPromises> in
    self.handleResult(obj)
    self.doSomethingDifferent(obj)
}.catch { error in
    self.handleError(error)
}

Or you can use obj -> Void to stop the chain

2
João Nunes On

Change it to:

firstly {
    // ...
}.then { obj -> Void in
    self.handleResult(obj)
    self.doSomethingDifferent(obj)
}.catch { error in
    self.handleError(error)
}
1
Vinicius Mangueira On

In Swift release 5.1 you can do that with Combine Framework, to solve this you can use the pattern Future. This is the same thing that Promise uses. Your code will look like this:

final class Future<Output, Failure> where Failure : Error

So just to warn you about promises in Swift and new framework.

4
Roman Podymov On

In PromiseKit 6.10.0 use done instead of then if you don't want to continue a chain with Thenable:

firstly {
    // ...
}.done { obj in
    self.handleResult(obj)
    self.doSomethingDifferent(obj)
}.catch { error in
    self.handleError(error)
}