1

How am I supposed to chain promises in PromiseKit 3.0 And Swift 2? I'm trying the following code:

let url = "https://httpbin/org/get";
let url2 = "https://httpbin/org/get";
firstly {
    NSURLSession.GET(url)
}.then { (json: NSDictionary) in
    NSURLSession.GET(url2) // Error in this line
}.then { (json: NSDictionary) in
    print("End of second request");
}

But I get the error "Cannot convert value of type 'URLDataPromise' to closure result type 'AnyPromise'" on line 6.

This is basically a sample retrieved from PromiseKit website, it is supposed to work, isn't? What am I doing wrong?

JAL
  • 41,701
  • 23
  • 172
  • 300
Eduardo Cobuci
  • 5,621
  • 4
  • 25
  • 27

2 Answers2

8

I figured it out. The problem was just that NSURLSession.GET doesn't return a NSDictionary so the following code is enough to resolve the problem:

let url = "https://httpbin/org/get";
let url = "https://httpbin/org/get";
let url2 = "https://httpbin/org/get";
firstly {
    NSURLSession.GET(url)
}.then { data in
    NSURLSession.GET(url2)
}.then { data in
    print("End of second request");
}

One important thing is that the Swift can't infer the type if your closure has more than one line of code, if that is the case you must specify the type in you closure declaration. Here goes some examples:

let url = "https://httpbin/org/get";
let url2 = "https://httpbin/org/get";
firstly {
    NSURLSession.GET(url)
}.then { data -> URLDataPromise in
    print("Two lines clojure with return");
    return NSURLSession.GET(url2)
}.then { data -> Void in
    print("Two lines clojure without return");
    print("Second line sample");
}
Eduardo Cobuci
  • 5,621
  • 4
  • 25
  • 27
  • 4
    Thank you! Your note about Swift not being able to infer the type of your closure if it has more than one line of code saved me going insane. I couldn't understand why some of my .then closures were happily inferring - and others required explicitly specifying the type (they were are single line!). – So Over It Feb 23 '16 at 10:58
  • Explanation on the [faq](http://promisekit.org/faq/) @SoOverIt, but yeah, is really annoying, specially when it happens in a `catch`, I miss Js – Jaime Agudo Dec 19 '16 at 16:34
1

First, I don't see an interface that can return a dictionary from NSURLSession.GET, so I'm using NSData. Additionally, you have to return the promise it each then closure in order to chain them together:

firstly {
    NSURLSession.GET(url)
}.then { (data) -> AnyPromise in
    return AnyPromise(bound: NSURLSession.GET(url2))
}.then { (secondData) in
    print("End of second request")
}
JAL
  • 41,701
  • 23
  • 172
  • 300
  • I don't think you need to bind `NSURLSession.GET(url2)` to a new `AnyPromise`. `NSURLSession.GET` returns `Promise`. Just specify the correct return type in your closure: `(data) -> Promise` – Jon Dec 09 '15 at 18:18
  • @Jon ah thanks! I was a little thrown off since I wasn't sue if the OP wanted to use `AnyPromise` or the strongly-typed `Promise`. – JAL Dec 09 '15 at 18:19
  • Fair enough. I actually don't understand the purpose of AnyPromise. It just seems to wrap a strongly-typed promise in a generic one and I don't know how that helps. Do you happen know of a scenario where you would need to use it? The only instances I see `AnyPromise(bound:` used in PromiseKit appear in the test suite. I can pose a SO question if this isn't appropriate to ask here. – Jon Dec 09 '15 at 18:35
  • 1
    @Jon happy to follow up here. I'm new to PromiseKit so I may be wrong as well. You would have to use `AnyPromise` if you had an Objective-C or mixed codebase. I was looking for a way to convert a `Promise` to `AnyPromise`, and `bound` seemed to work for my needs. But I definitely can't say for sure if this is the "right" way to do this. – JAL Dec 09 '15 at 18:36
  • That makes sense. Thanks! – Jon Dec 09 '15 at 18:38