【问题标题】:How can I prevent nested completion blocks in Swift 3?如何防止 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
  • 感谢大家的帮助和资源!
  • 您还可以使用 DispatchQueues 顺序运行您的网络请求。不过,我也推荐使用 PromiseKit,一旦你掌握了它,它比任何内置的处理异步请求的方式都要强大和方便。

标签: swift nested completionhandler


【解决方案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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-18
      • 2023-02-14
      • 1970-01-01
      相关资源
      最近更新 更多