user5855868
user5855868

Reputation: 97

Alamofire wait for response

I have a method in my application that is called getAllPosts() this is a GET request that gets data, but inside that method I´m doing a POST request to get the access token that needs to be passed with the getAllPosts()request. So basically like this:

func getAllPosts(){
    let token = getToken()
    Alamofire.request(.GET...)
}

func getToken(){
    Alamofire.request(.POST...)
}

So the issue that I´m having is that the getToken function is called but not completed and the getAllPosts function makes the GET request before the token is set.

I´m not sure how to wait for the token to be set in the getToken() function before I continue with the getAllPosts request.

Appreciate some help with this issue.

Upvotes: 0

Views: 1708

Answers (2)

Cylowatt
Cylowatt

Reputation: 56

Alamofire is making network requests, and therefore runs asynchronously in a background thread. If you take a look at examples at Alamofire's GitHub page, you will see that they use a syntax like this:

Alamofire.request(.POST ...)
    .validate()
    .responseString { response in
        // This code will be executed after the token has been fetched.
    }

So you'll want to do something like this:

func getAllPosts() {
    // This notation allows to pass a callback easily.
    getToken { appToken in

        // Unwrap the value of appToken into constant "token".
        guard let token = appToken else {
            // Handle the situation if the token is not there
            return
        }

        // The token is available to use here.
        Alamofire.request(.GET ...)
           ...
    }
}

/**
Gets the token.

- Parameters:
    - callback: Block of code to execute after the token has been fetched.
                The token might be nil in case some error has happened.
*/
func getToken(callback: (appToken: String?) -> Void) {
    Alamofire.request(.POST ...)
        .validate()
        .responseString { response in 
            // Check whether the result has succeeded first.
            switch response.result {
            case .Success:
                // Successful result, return it in a callback.
                callback(appToken: response.result.value)
            case .Failure:
                // In case it failed, return a nil as an error indicator.
                callback(appToken: nil)
            }
        }
}

My answer includes a bit more error handling, but the idea is that you simply use a function inside the .responseString/.responseJSON/etc. call.

@Steelzeh's answer demonstrates the same idea, but instead of calling getAllPosts() first, they call getToken() first, and then pass the result to getAllPosts().

Upvotes: 2

Steelzeh
Steelzeh

Reputation: 284

Change it to this

func getAllPosts(){
    Alamofire.request(.GET...)
}

func getToken(){
    Alamofire.request(.POST...) {
        //SUCCESS BLOCK
        self.getAllPosts()
    }
}

Now instead of calling getAllPosts you should first call getToken and when the POST request is complete it goes to the Success Block where it fires getAllPosts() which now has the token.

A different way to solve this would be to make the POST request Synchronised instead of using Alamofire which is Async. Synchronised requests wait for response before continuing

Upvotes: 1

Related Questions