简体   繁体   中英

Delay task until completed

It is a very common question for people to ask "How do I delay a function or a chunk of code?" but that is not what I need here.

I need my code to wait until a certain task is complete, otherwise my function receives an error that I have no access_token (as the code doesn't wait for fetching the data from the Spotify server).

Here is my code so far, with the attempt to add a DispatchGroup :

func getAccessToken() throws -> Spotify.JSONStandard {
    var accessToken: Spotify.JSONStandard!

    let group = DispatchGroup() // <- Create group
    group.enter() // <- Enter group

    Alamofire.request("https://accounts.spotify.com/api/token", method: .post, parameters: spotify.parameters, headers: nil).responseJSON(completionHandler: {
        response in
        // Check if response is valid
        if let newValue = response.result.value as? Spotify.JSONStandard {
            accessToken = newValue
        }

        group.leave() // <- Leave group
    })

    group.wait() // <- Wait until task is completed

    // \/ Delay this code until complete \/
    if accessToken != nil {
        return accessToken
    }
    else {
        throw SpotifyError.failedToGetAccessToken
    }
    // /\                                /\
}

Without the groups, my code throws SpotifyError.failedToGetAccessToken (the access_token is nil ).

However, after adding the groups, my code just hangs and waits forever. How can I delay this code from being completed?

I know getting the token has no issues, as if I remove the return and place a print within the request, I get my expected result.

If you have any questions, please ask

Don't try to make an asynchronous task synchronous

This is a solution with a completion handler and a custom enum for convenience

enum Result {
    case success(Spotify.JSONStandard), failure(Error)
}

func getAccessToken(completion: @escaping (Result)->()) {
    Alamofire.request("https://accounts.spotify.com/api/token", method: .post, parameters: spotify.parameters, headers: nil).responseJSON(completionHandler: {
        response in
        // Check if response is valid
        if let newValue = response.result.value as? Spotify.JSONStandard {
            completion(.success(newValue)
        } else {
            completion(.failure(SpotifyError.failedToGetAccessToken))
        }
    })
}

and call it

getAccessToken { result in
   switch result {
     case .success(let token) : // do something with the token
     case .failure(let error) : // do something with the error
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM