【发布时间】:2019-11-05 18:18:02
【问题描述】:
我在 Swift 中实现了PromiseKit 以避免带有完成块的回调地狱。我需要知道将 Promise 链接在一起以初始化具有其他关联对象的自定义对象的最佳方法。例如,Comment 对象附加了一个 User 对象。
首先我从数据库中获取comments,它们在数据库结构中都有uid 属性。我最终希望得到一个comments 数组,每个数组都附加了正确的用户,所以我可以同时加载comment 和user 数据。使用完成块,这一切似乎都容易得多,但我是一个总 Promise noob 所以 idk。
这是控制器中处理 fetch 的代码
CommentsService.shared.fetchComments(withPostKey: postKey)
.then { comments -> Promise<[User]> in
let uids = comments.map({ $0.uid })
return UserService.shared.fetchUsers(withUids: uids)
}.done({ users in
// how to init Comment object with users now?
})
.catch { error in
print("DEBUG: Failed with error \(error)")
}
这里是评论获取功能:
func fetchComments(withPostKey postKey: String) -> Promise<[Comment]> {
return Promise { resolver in
REF_COMMENTS.child(postKey).observeSingleEvent(of: .value) { snapshot in
guard let dictionary = snapshot.value as? [String: AnyObject] else { return }
let data = Array(dictionary.values)
do {
let comments = try FirebaseDecoder().decode([Comment].self, from: data)
resolver.fulfill(comments)
} catch let error {
resolver.reject(error)
}
}
}
}
这里是获取用户功能
func fetchUsers(withUids uids: [String]) -> Promise<[User]> {
var users = [User]()
return Promise { resolver in
uids.forEach { uid in
self.fetchUser(withUid: uid).done { user in
users.append(user)
guard users.count == uids.count else { return }
resolver.fulfill(users)
}.catch { error in
resolver.reject(error)
}
}
}
}
这里是评论对象:
struct Comment: Decodable {
let uid: String
let commentText: String
let creationDate: Date
var user: User?
}
完成块就是这么简单,开始认为 Promise 不值得?
func fetchComments(withPostKey postKey: String, completion: @escaping([Comment]) -> Void) {
var comments = [Comment]()
REF_COMMENTS.child(postKey).observe(.childAdded) { (snapshot) in
guard let dictionary = snapshot.value as? [String: AnyObject] else { return }
guard let uid = dictionary["uid"] as? String else { return }
UserService.shared.fetchUser(withUid: uid, completion: { (user) in
let comment = Comment(user: user, dictionary: dictionary)
comments.append(comment)
completion(comments)
})
}
}
【问题讨论】:
-
我更喜欢 Rx 而不是 Promise 工具包,但在任何情况下,
then块在概念上就像一个map,如果你接受一个Promise<T>但返回一个U然后他输出是另一个Promise<U>。then也可以像 flatMap 一样,如果你有一个Promise<T>但返回一个Promise<U>,那么输出是Promise<U>而不是Promise <Promise<U>>。在任何情况下,您都希望 a 从用户开始,因此返回Promise<User>或只是一个`用户`,然后您想要获取 cmets,因此从下一个then block返回Promise<Comments>或只是Comments -
我需要评论结构中的
userIds,以便知道要获取哪些用户,因此必须先获取 cmets
标签: swift promise promisekit