8

I am new to promises in Swift and using PromiseKit to try and create a very simple response in a playground and attempt to use it. I have the following code:

import UIKit
import PromiseKit

func foo(_ error: Bool) -> Promise<String> {
  return Promise { fulfill, reject in
    if (!error) {
      fulfill("foo")
    } else {
      reject(Error(domain:"", code:1, userInfo:nil))
    }
  }
}

foo(true).then { response -> String in {
  print(response)
  }
}

However I get the following error:

error: MyPlayground.playground:11:40: error: cannot convert value of type '() -> ()' to closure result type 'String'
foo(true).then { response -> String in {
aturan23
  • 4,798
  • 4
  • 28
  • 52
John Mike
  • 1,895
  • 3
  • 17
  • 26

1 Answers1

4

The error is being thrown because the closure you're passing to then purports to return a String, but no such value is ever returned. Unless you plan on returning a String somewhere in that closure, you need to change the closure's return type to Void, as follows:

foo(true).then { response -> Void in
    print(response)
}

Note that closures with the return type Void can have their return type omitted. Also, you have an extraneous { in the code in your question (I'm assuming this doesn't exist in your actual code, since it compiles).

In addition to that issue, Error has no accessible initializers—the initializer you're using in your code actually belongs to NSError, and thus your reject call needs to look like:

reject(NSError(domain:"", code:1, userInfo:nil))
aaplmath
  • 1,717
  • 1
  • 14
  • 27
  • Thanks for the answer. Seems like I have not understood promises well enough. If response -> Void, does that mean fulfill("foo") will still work as expected - in that I will have access to "foo" in the .then as the response? – John Mike Jul 01 '17 at 21:51
  • Yes. The type after `->` just says what, if anything, _you_ are returning from the closure; `response` remains unchanged. – aaplmath Jul 01 '17 at 21:53
  • I've also tried the ammendments in a playground but it doesn't seem to print out "foo". On the right hand side instead it says "Promise: UnsealedState"? – John Mike Jul 01 '17 at 21:54
  • Right, because the `response` is going to be a String, unless an error is thrown (in which case `catch` would be called). `response` does not hold a reference back to `foo`; rather, it contains the response from the original promise (which is of type `Promise`, and thus `response` is a String). But, in your example, passing `true` to `foo` causes an error, meaning that `then` will never be called. Use a `catch` block (which has the error as its parameter) to handle errors. – aaplmath Jul 01 '17 at 22:03
  • I see, but even if I pass `false` to trigger `.then` it still doesn't print "foo" and has the same "Promise: UnsealedState" on the right hand side – John Mike Jul 01 '17 at 22:09
  • Make sure you have imported `PlaygroundSupport` and that you have included the line `PlaygroundPage.current.needsIndefiniteExecution = true`. – aaplmath Jul 01 '17 at 22:11
  • 1
    Worked perfectly, you're awesome! – John Mike Jul 01 '17 at 22:19