How to make app wait until Firebase request is finished

情到浓时终转凉″ 提交于 2019-12-18 12:39:27

问题


I want my method to wait until Firebase request finished

uploadSingUpInfo returns before the Firebase request finishes, and this is a problem for me - some method returns nil.

static func uploadSingUpInfo(fullName:String,email:String,password:String)->String{
    rootRef = FIRDatabase.database().reference()
    var returnVlue="not valid"

    FIRAuth.auth()?.createUserWithEmail(email, password: password) { (user, error) in
        if (error != nil){
            returnVlue=(error?.userInfo["error_name"]) as! String
        }
        else{

            let newUser = [
                "username": fullName
            ]
            rootRef.childByAppendingPath("User")
                .childByAppendingPath((user?.uid)!).setValue(newUser)
            NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isLogin")
            NSUserDefaults.standardUserDefaults().setObject(email, forKey: "email")
            NSUserDefaults.standardUserDefaults().setObject(user?.uid, forKey: "user_ID")
            print(NSUserDefaults.standardUserDefaults().objectForKey("user_ID"))
            returnVlue="valid"

        }
    }

    return returnVlue

}

回答1:


Don't use Firebase as functions that return values - it goes against it's asynchronous nature.

Plan code structure that allows Firebase to perform it's task and then within the closure (block) go to the next step.

For example: In your code, change the function to not return anything and within the createUserBlock, as the last line instead of return, call the next function to update your UI.

static func uploadSingUpInfo(fullName:String,email:String,password:String) {

    rootRef = FIRDatabase.database().reference()

    FIRAuth.auth()?.createUserWithEmail(email, password: password) { (user, error) in
        if (error != nil){
            showUserAnError(error)
        } else {

            let newUser = [
                "username": fullName
            ]
            rootRef.childByAppendingPath("User")
                .childByAppendingPath((user?.uid)!).setValue(newUser)
            NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isLogin")
            NSUserDefaults.standardUserDefaults().setObject(email, forKey: "email")
            NSUserDefaults.standardUserDefaults().setObject(user?.uid, forKey: "user_ID")
            print(NSUserDefaults.standardUserDefaults().objectForKey("user_ID"))
            continueLoginProcess()  //reload the ui or whatever step is next
        }
      }
    }



回答2:


In your code, the method returns before the firebase request completes so the value of returnVlue will not be set.

Normal Functions don't wait for async functions to finish running ;- because that's kind of the point of an async function. isn't it?

So if you want your uploadSingUpInfo to wait until createUserWithEmail has finished, then you have to make createUserWithEmail an async function as well by using completionHandlers:

func uploadSingUpInfo(fullName: String, email: String, password: String, completion: (result: String) -> Void) {
    FIRAuth.auth()?.createUserWithEmail(email, password: password) {
     (user, error) in
       if (error != nil){
           returnVlue=(error?.userInfo["error_name"]) as! String
       }
       else{

           let newUser = [
               "username": fullName
           ]
           rootRef.childByAppendingPath("User")
            .childByAppendingPath((user?.uid)!).setValue(newUser)
           NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isLogin")
           NSUserDefaults.standardUserDefaults().setObject(email, forKey: "email")
           NSUserDefaults.standardUserDefaults().setObject(user?.uid, forKey: "user_ID")
           print(NSUserDefaults.standardUserDefaults().objectForKey("user_ID"))
           returnVlue="valid"

       }

       completion(returnVlue);
    }
}

And this is how you would call this method :

uploadSingUpInfo(<arguments>) {
    (result: String) in             //this is what you pass to completion handler.
     print("got back: \(result)")
}

See this article for a better idea.




回答3:


Instead of returning a value from that function. You can call another function inside the firebase method at the "very end" of the method. This will ensure that whatever function you need to do next, is executed at the end when Firebase is done processing your request

FIRAuth.auth()?.createUserWithEmail(email, password: password) { (user, error) in
        if (error != nil){
            returnVlue=(error?.userInfo["error_name"]) as! String
        }
        else{

            let newUser = [
                "username": fullName
            ]
            rootRef.childByAppendingPath("User")
                .childByAppendingPath((user?.uid)!).setValue(newUser)
            NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isLogin")
            NSUserDefaults.standardUserDefaults().setObject(email, forKey: "email")
            NSUserDefaults.standardUserDefaults().setObject(user?.uid, forKey: "user_ID")
            print(NSUserDefaults.standardUserDefaults().objectForKey("user_ID"))
            returnVlue="valid"

        }
callAnotherFunctionWhenFinished()
    }


来源:https://stackoverflow.com/questions/39190795/how-to-make-app-wait-until-firebase-request-is-finished

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!