Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use swift-4 Promises then, done, catch and other blocks

I would like to learn about promises in swift-4. How to use multiple then statements and done, catch blocks.

Here I am trying to get the value from the promise. But I'm getting errors. Could someone help me to understand promises?

Here is my code.

import UIKit
import PromiseKit

struct User {
    var firstname : String?
    var lastname  : String?
}

struct APIError {
    var message : String?
}

class ViewController : UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let userPromise : Promise = self.getUserDetails()
        userPromise.then { user -> Void in
            //print(user.f)
        }
    }

    func getUserDetails()->Promise<User> {
        return Promise<User> { resolve in
            let user  = User(firstname: "Scot", lastname: "dem")
            if ((user.firstname?.count) != nil) {
                resolve.fulfill(user)
            } else {
                let error = APIError(message: "User not valid")
                resolve.reject(error as! Error)
            }
        }
    }
}

Once I get the user details I want to make a full name, uppercase promises which are dependent on userPromise.

I would like to use multiple then, done, finally blocks. Just want to understand usage.

Why I'm getting an error here when we use userPromise.then { user -> Void in

what should I give inside the block

like image 687
Damodar Avatar asked Apr 29 '18 21:04

Damodar


1 Answers

In PromiseKit 6, then can no longer return Void. This is mainly due to the tuplegate issue in Swift 4.

Quote from PromieKit 6 Release News

With PromiseKit our then did multiple things, and we relied on Swift to infer the correct then from context. However with multiple line thens it would fail to do this, and instead of telling you that the situation was ambiguous it would invent some other error. Often the dreaded cannot convert T to AnyPromise. We have a troubleshooting guide to combat this but I believe in tools that just work, and when you spend 4 years waiting for Swift to fix the issue and Swift doesn’t fix the issue, what do you do? We chose to find a solution at the higher level.

So we split then into then, done and map.

  • then is fed the previous promise value and requires you return a promise.
  • done is fed the previous promise value and returns a Void promise (which is 80% of chain usage)
  • map is fed the previous promise value and requires you return a non-promise, ie. a value.

Hence .then { (user) -> Void in is no longer valid and that's why you're getting an error.
It's now designed to return a Thenable like so:

userPromise.then { user -> Promise<User> in
    //return yet another promise
}

The .then that used to return Void is now it's own .done.
i.e:

userPromise.done { (user) in
    print(user)
}

So when you mix 'em up:

We get:

userPromise
    .then { (user) -> Promise<User> in
        //return another Promise
        return self.uppercasePromise(on: user)
    }
    .done { (user) in
        /*
         Depending on your sequence, no more promises are left 
         and you should have a matured user object by now
         */
        print(user)
    }
    .catch { (error) in
        print(error)
    }
    .finally {
        print("finally")
    }

func uppercasePromise(on user: User) -> Promise<User> {
    /*
     Didn't understand your statement but do whatever you meant when you said:

     "Once I get the user details I want to make a full name, "
     uppercase promises which are dependent on userPromise."
     */
    return Promise { seal in
        seal.fulfill(user)
    }
}
like image 195
staticVoidMan Avatar answered Oct 10 '22 18:10

staticVoidMan