1

I have 3 promises, each works individually:

DataManager.reverseGeoCodePromise("42.527328", longitude: "-83.146928").then { data in
    print("Zip \(data)")
}

DataManager.getEnviroUVWithZipPromise("48073").then { data in
    print("UV \(data.getUVIndex())")
}

DataManager.getCurrentForZipPromise("48073").then { data in
    print("AirNow \(data[0].Latitude)")
}

I have been trying to follow (sparce) swift documentation on promisekit 3 (and exhausted google and stack overflow). My attempt at chaining these async methods is not acting synchronously at all - all the print(data) are null, but the breakpoints in the methods shows data.

DataManager.reverseGeoCodePromise("42.527328", longitude: "-83.146928").then { data in
    print("Promise Zip \(data)")
}.then { data -> Void in
    DataManager.getEnviroUVWithZipPromise("48073")
    print("Promise Enviro \(data)")
}.then { data -> Void in
    DataManager.getCurrentForZipPromise("48073")
    print("Promise AirNow \(data)")
}.error { error in
    print("Promise doh!")
}

I would like data from the first call (zip) to be passed to subsequent calls and to be able to work with data from all calls after the last. Any insight greatly appreciated!

Slava Vedenin
  • 58,326
  • 13
  • 40
  • 59
Jim Peters
  • 31
  • 4
  • Check out my answer here for syntax. http://stackoverflow.com/questions/34501537/ambigous-use-of-recover-error-while-using-promisekit/34502275#34502275 – Jon Jan 25 '16 at 15:59

1 Answers1

0

Your issue is that your closures are returning Void instead of Promise<T>. The then block doesn't expect anything to be returned so it continues without waiting for a promise to be fulfilled or rejected.

Here is a full example for you. You can paste it in the PromiseKit playground to test it out.

var zipcode: String?

UIApplication.sharedApplication().networkActivityIndicatorVisible = true

firstly {

    return DataManager.reverseGeoCodePromise("42.527328", longitude: "-83.146928")

}.then { (data: String) -> Promise<String> in
    // ^ I expect to receive a string. I promise to return a string        

    zipcode = data
    // ^ Store zip code so it can be used further down the chain

    print("Returned from reverseGeoCodePromise: \(data)")
    return DataManager.getEnviroUVWithZipPromise(zipcode!)

}.then { (data: String) -> Promise<String> in
    // ^ I expect to receive a string. I promise to return a string

    print("Returned from getEnviroUVWithZipPromise: \(data)")
    return DataManager.getCurrentForZipPromise(zipcode!)

}.then { (data: String) -> Void in
    // ^ I expect to receive a string. I return nothing

    print("Returned from getCurrentForZipPromise: \(data)")

}.always {

    UIApplication.sharedApplication().networkActivityIndicatorVisible = false

}.error { error in

    switch error {
    case DataManagerError.FailedDueToX:
        print("got an error")
    default:
        print("unknown error")
    }

}

Example custom error type:

enum DataManagerError: ErrorType {
    case FailedDueToX
}

Example data manager promises:

class DataManager {
    static func reverseGeoCodePromise(lat: String, longitude: String) -> Promise<String> {
        return Promise { fulfill, reject in
            if 1 == 1 {
                fulfill("48073")
            } else {
                reject(DataManagerError.FailedDueToX)
            }
        }
    }

    static func getEnviroUVWithZipPromise(zip: String) -> Promise<String> {
        return Promise { fulfill, reject in
            if 1 == 1 {
                fulfill("Two")
            } else {
                reject(DataManagerError.FailedDueToX)
            }
        }
    }

    static func getCurrentForZipPromise(zip: String) -> Promise<String> {
        return Promise { fulfill, reject in
            if 1 == 1 {
                fulfill("Three")
            } else {
                reject(DataManagerError.FailedDueToX)
            }
        }
    }

}
Jon
  • 3,208
  • 1
  • 19
  • 30
  • note that you don't have to start off using `firstly`, I just prefer how it looks. – Jon Jan 25 '16 at 16:40
  • Thank you! Actually, two of the methods return custom objects, not String ... posted here: – Jim Peters Jan 25 '16 at 18:34
  • I used Strings just for illustration purposes. You can replace with data types to suit your exact scenario. Regarding your zip code comment, you can store it outside of the promise chain. I'll update my answer to show you how. – Jon Jan 25 '16 at 19:35
  • understood, I posted a working example in the original post, below your answer. Not seeing that at this point - probably SO defacto behavior being not met (newbie). Looking forward to your update. Can I also use the neturn value from the second call in the result from the third? – Jim Peters Jan 25 '16 at 19:46
  • Your changes came in as a recommended edit to my answer. Moderators rejected the edit because you asked additional questions. If you need to pose followup questions, just use the comments area (as you just did) or edit your original question. – Jon Jan 25 '16 at 19:58
  • Thank you. I thought I tried declaring a zip outside ... I'll give it another go. Assuming I can to that for the result of the 2nd call. – Jim Peters Jan 25 '16 at 20:30