首页 > 解决方案 > 在 Swift 中链接 Promise 以初始化自定义对象

问题描述

PromiseKit在 Swift 中实现以避免带有完成块的回调地狱。我需要知道将 Promise 链接在一起以初始化具有其他关联对象的自定义对象的最佳方法。例如Comment,一个User对象附加了一个对象。

首先,我comments从数据库中获取,它们在数据库结构中都有一个uid属性。我最终希望得到一个 数组comments,每个数组都附加了正确的用户,所以我可以同时加载commentuser数据。使用完成块,这一切似乎都容易得多,但我完全是个Promise菜鸟,所以我很不喜欢。

这是控制器中处理获取的代码

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)
            })
        }
    }

标签: swiftpromisepromisekit

解决方案


好的,我想我明白您要做什么。问题是您需要与用户一起捕获评论,以便您可以一起返回然后将它们组合起来。它应该看起来像这样:

CommentsService.shared.fetchComments(withPostKey: postKey)
  .then { comments -> Promise<[Comment], [User]> in
    let uids = comments.map({ $0.uid })
    return UserService.shared.fetchUsers(withUids: uids)
      .then { users in
        return Promise<[Comment], [User]>(comments, users)
      }
    }.done({ combined in
      let (comments, users) = combined
      //Do combiney stuff here
    })
      .catch { error in
        print("DEBUG: Failed with error \(error)")
}

转换为 [评论] -> [用户] -> ([评论], [用户]) -> [附有用户的评论]


推荐阅读