如何防止 Swift 3 中的嵌套完成块?
Posted
技术标签:
【中文标题】如何防止 Swift 3 中的嵌套完成块?【英文标题】:How can I prevent nested completion blocks in Swift 3? 【发布时间】:2017-06-01 07:42:39 【问题描述】:我在下面提供的代码中有一系列嵌套的完成块。这是因为我需要在后台发出单独的网络请求以抽象数据以用于下一个方法,该方法提供另一个完成块,依此类推。有没有办法解决?非常感谢任何提示!
func fetchNearbyUsers(forCurrentUser user: User, completionHandler: usersCompletionHandler?)
self.fetchAllUsers(completionHandler: (users: [User]) in
ChatProvider.sharedInstance.fetchAllChatrooms(completionHandler: (chatrooms: [Chatroom]) in
self.validateNewUsers(currentUser: user, users: users, chatrooms: chatrooms, completionHandler: (validUsers: [User]) in
guard validUsers.isEmpty == false else
completionHandler?([])
return
completionHandler?(validUsers)
)
)
)
【问题讨论】:
它不会改变你正在做的事情的逻辑 - 但它可以通过从完成处理程序中对下一步进行函数调用来使其更具可读性,并单独拥有代码 你也可以查看 PromiseKit 看到这个答案***.com/a/44092277/1825618 感谢大家的帮助和资源! 您还可以使用 DispatchQueues 顺序运行您的网络请求。不过,我也推荐使用 PromiseKit,一旦你掌握了它,它比任何内置的处理异步请求的方式都要强大和方便。 【参考方案1】:这里的一个选择是使用高阶工厂函数(即返回其他函数的函数)将块分解成它们自己的函数...
func fetchNearbyUsers(forCurrentUser user: User, completionHandler: @escaping usersCompletionHandler = _ in )
self.fetchAllUsers(completionHandler: self.allUsersFromChatrooms(user: user, completionHandler: completionHandler))
func allUsersFromChatrooms(user: User, completionHandler: @escaping usersCompletionHandler) -> ([User]) -> Void
return users in
ChatProvider.sharedInstance.fetchAllChatrooms(completionHandler: self.validatedUsersInChatrooms(user: user, users: users, completionHandler: completionHandler))
func validatedUsersInChatrooms(user: User, users: [User], completionHandler: @escaping usersCompletionHandler) -> ([Chatroom]) -> Void
return chatrooms in
self.validateNewUsers(currentUser: user, users: users, chatrooms: chatrooms, completionHandler: completionHandler)
在上面的代码中,validatedUsersInChatrooms
将返回一个函数,该函数接受一组聊天室,并使用经过验证的用户调用提供的完成处理程序。函数allUsersFromChatrooms
返回一个接受用户数组的函数,然后获取聊天室并使用聊天室中经过验证的用户数组调用提供的完成处理程序。
还请注意,我更改了您的 fetchNearbyUsers
函数以接受完成块并默认为不执行任何操作的块,而不是使用可选块。感觉干净多了。
【讨论】:
【参考方案2】:为什么不调用一个函数并使用一些布尔值来确保两者都是完整的。这是一些伪代码
var completeA = false
var completeB = false
func doStuff
asyncStuffA(stuff
asyncStuffB(stuff
, completion:
completeB = true
completionHandler()
)
, completion:
completeA = true
completionHandler()
)
func completionHandler()
if completeA && completeB
// Both are complete
completeA = false
completeB = false
【讨论】:
以上是关于如何防止 Swift 3 中的嵌套完成块?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Objective-C 的完成块转换为 Swift?