0

I am attempting my first foray into swift promises with PromiseKit, after some experience with doing them with bluebird in node. My original service function for authentication with a callback looks like this:

private func requestNewToken(email : String, password: String,
completion: (success: Bool, token: String?, userId : String?, message: String? ) -> Void) {

Alamofire.request(Router.Authenticate(email, password).URLRequest)
    .responseJSON { request, response, result in
        switch result {
        case .Success(let data):
            let jsonData = JSON(data)

            let success = jsonData["success"].bool!
            let message = jsonData["message"].string!

            if(success) {
                let token = jsonData["token"].string
                let userId = jsonData["_id"].string

                self.deleteSavedUser()
                self.saveUserToCoreData(email, password: password, token: token!, userId: userId!)
                completion(success: true, token: token, userId: userId, message:  message)
                return
            }

            completion(success: false, token: nil, userId: nil, message: message)
            print("Token request failed with error: \(message)")

        case .Failure(_, let error):
            print("Request failed with error: \(error)")
            completion(success: false, token: nil, userId : nil, message: nil)
        }
}
}

I'm attempting to rewrite to something like this:

private func requestNewTokenPromise(email : String, password:
String) -> Promise<UserLoginData?>{         
 return Promise{ fulfill, reject in             
   Alamofire.request(Router.Authenticate(email,password).URLRequest)
        .responseJSON { request, response, result in
            switch result {
            case .Success(let data):
                let jsonData = JSON(data)
                fulfill(jsonData)
            case .Failure(_, let error):
                print("Request failed with error: \(error)")
                reject(error)
            }
        }
}.then { json in

            let success = json["success"].bool!
            let message = json["message"].string!

            if(success) {
                let token = json["token"].string
                let userId = json["_id"].string

                self.deleteSavedUser()
                self.saveUserToCoreData(email, password: password, token: token!, userId: userId!) //sets the class's savedUser property

                return Promise(self.savedUser);
            }

            return Promise(nil);            
 }  
}

However, I get an error on my then line:

AuthenticationService.swift:147:6: Cannot convert return expression of type 'Promise<AnyObject?>' 
(aka 'Promise  Optional<AnyObject>> ') to return type 'Promise<UserLoginData?>' (aka 'Promise<Optional<UserLoginData>>')

I had thought by resolving the promise with Promise() that I'd be fulfilling the original promise type. Where am I going wrong?

Eric H
  • 1,323
  • 3
  • 14
  • 29

1 Answers1

0

I was incorrect in assuming code can be sent straight to promises, sometimes you just need to wrap a callback:

public func login(email: String, password: String) -> Promise<UserLoginData> {
        return Promise { fulfill, reject in
            requestNewToken(email, password: password){
                success, returnToken, userId, message in

                if(!success){
                    reject(LoginError.LoginFailed(message))
                    return
                }
                self.deleteSavedUser()
                self.saveUserToCoreData(email, password: password, token: returnToken!, userId: userId!)
                let user = self.fetchUserFromCoreData()
                fulfill(user!)
            }
        }
    }
Eric H
  • 1,323
  • 3
  • 14
  • 29
  • Code can be sent straight to promises, you were just missing type data. – Benjamin Gruenbaum May 07 '16 at 19:02
  • You are correct when you have complete control over the code. In this particular case since I'm using a 3rd party library, I'm constrained to the mechanisms that they provide. Callback was my only option to work with Alamofire, so it was better to wrap it, and put my code inside of a returned promise. – Eric H May 08 '16 at 19:09
  • PromiseKit used to wrap alamofire automatically when I talked to mxcl about it a year and a half ago. Wonder if that still works. Also, note that I was merely pointing out _why_ you needed your solution - I didn't say it's wrong. – Benjamin Gruenbaum May 08 '16 at 19:13
  • I'll have to look into the alamofire/promisekit thing, thanks! – Eric H May 08 '16 at 21:27