Sync nested asynchronous task

I have nested asynchronous tasks. The function below, following this thread: loadEpisodes (loads a list of episodes) -> use the array from completion to loop through each episode, and load comments (another asynchronous task) for a specific episode.

The problem is this: comletion (fullEpisodes) excuted before completing the comment loading task. I tried using the Dispatch Group (second block of code), but it does not work.

func loadComments(comletion: @escaping ([Episode]) -> Void){ loadEpisodes(completion: { episodes in var fullyEpisodes = [Episode]() for episode in episodes { WebService().load(resource: episode.comment, comletion: { comments in if let comments = comments { let _episode = Episode(id: episode.id, title: episode.title, comments: comments) fullyEpisodes.append(_episode) print("done") } }) } comletion(fullyEpisodes) }) } 

Implemented dispatch group:

 func loadComments(comletion: @escaping ([Episode]) -> Void){ loadEpisodes(completion: { episodes in var fullyEpisodes = [Episode]() let group = DispatchGroup() for episode in episodes { group.enter() WebService().load(resource: episode.comment, comletion: { comments in if let comments = comments { let _episode = Episode(id: episode.id, title: episode.title, comments: comments) fullyEpisodes.append(_episode) print("done") } }) group.leave() } group.wait() group.notify(queue: .main, execute: { comletion(fullyEpisodes) }) }) } 

When I try to replace the comment download request with "print (" something ")" (and not with the new async task), the Dispatch group works.

+5
source share
1 answer

In your second example (a), move group.leave() to close the completion handler load() ; and (b) completely remove group.wait() .

 func loadComments(comletion: @escaping ([Episode]) -> Void){ loadEpisodes(completion: { episodes in var fullyEpisodes = [Episode]() let group = DispatchGroup() for episode in episodes { group.enter() WebService().load(resource: episode.comment, comletion: { comments in if let comments = comments { let _episode = Episode(id: episode.id, title: episode.title, comments: comments) fullyEpisodes.append(_episode) print("done") } group.leave() }) // group.leave() } //group.wait() group.notify(queue: .main, execute: { comletion(fullyEpisodes) }) }) } 

or, reading this a little with closing syntax and fixing completion spelling:

 func loadComments(completion: @escaping ([Episode]) -> Void) { loadEpisodes { episodes in var fullyEpisodes = [Episode]() let group = DispatchGroup() for episode in episodes { group.enter() WebService().load(resource: episode.comment) { comments in if let comments = comments { let _episode = Episode(id: episode.id, title: episode.title, comments: comments) fullyEpisodes.append(_episode) } group.leave() } } group.notify(queue: .main) { completion(fullyEpisodes) } } } 
+4
source

Source: https://habr.com/ru/post/1260716/


All Articles