我有一个方法可以调用三个函数,每个函数向Firebase发出请求并在完成处理程序中传回数据。一旦完成了来自2个完成处理程序的数据,我就会调用另一个方法传入数据并发回有效结果。像这样的嵌套块是设计不佳的标志吗?
func fetchNearbyUsers(for 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)
})
})
})
}
//其他方法
func fetchAllUsers(completionHandler: usersCompletionHandler?) {
var users: [User] = []
let group = DispatchGroup()
let serialQueue = DispatchQueue(label: "serialQueue")
DatabaseProvider.sharedInstance.usersDatabaseReference.observe(.value, with: {
snapshot in
guard let data = snapshot.value as? [String: AnyObject] else { return }
for (_, value) in data {
guard let values = value as? [String: AnyObject] else { return }
guard let newUser = User(data: values) else { return }
group.enter()
newUser.fetchProfileImage(completionHandler: { (image) in
serialQueue.async {
newUser.profileImage = image
users.append(newUser)
group.leave()
}
})
}
group.notify(queue: .main, execute: {
completionHandler?(users)
})
})
}
func fetchAllChatrooms (completionHandler: chatroomsHandler?) {
var chatrooms = [Chatroom]()
let group = DispatchGroup()
let serialQueue = DispatchQueue(label: "serialQueue")
DatabaseProvider.sharedInstance.chatroomsDatabaseReference.observe(.value, with: { snapshot in
guard let data = snapshot.value as? [String: AnyObject] else { return }
for (_, value) in data {
guard let value = value as? [String: AnyObject] else { return }
guard let newChatroom = Chatroom(data: value) else { return }
group.enter()
self.fetchChatroomUsers(chatroom: newChatroom, completionHandler: { (chatroom) in
serialQueue.async {
chatrooms.append(newChatroom)
group.leave()
}
})
}
group.notify(queue: .main, execute: {
completionHandler?(Array(Set<Chatroom>(chatrooms)))
})
})
}
private func validateNewUsers(currentUser: User, users: [User], chatrooms: [Chatroom], completionHandler: usersCompletionHandler?) {
let chatPartners = self.chatPartners(currentUser: currentUser, chatrooms: chatrooms)
let validUsers = users
.filter { currentUser.id != $0.id }
.filter { currentUser.distanceFromUser(atLocation: $0.coordinates) <= 8046.72 }
.filter { !chatPartners.contains($0.id) }
completionHandler?(validUsers)
}
private func chatPartners (currentUser: User, chatrooms: [Chatroom]) -> Set<String> {
var results = [String]()
for chatroom in chatrooms {
if currentUser.id == chatroom.firstUserId {
results.append(chatroom.secondUserId)
} else if currentUser.id == chatroom.secondUserId {
results.append(chatroom.firstUserId)
}
}
return Set(results)
}