Цепочка обещает в Swift инициализировать пользовательский объект - PullRequest
1 голос
/ 05 ноября 2019

Я реализовал PromiseKit в Swift, чтобы избежать ада обратного вызова с блоками завершения. Мне нужно знать, как лучше всего объединить обещания для инициализации пользовательских объектов, имеющих другие связанные объекты. Например, объект Comment, к которому прикреплен объект User.

Сначала я выбираю comments из БД, у всех которых есть свойство uid в структуре БД. В конечном итоге я хочу получить массив comments, где к каждому из них прикреплен правильный пользователь, поэтому я могу загрузить данные comment и user. Все это выглядело намного проще с блоками завершения, но я в целом Promise noob, так что idk.

Вот код в контроллере, который обрабатывает выборку

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

Насколько просто с блоками завершения начать думать, что Обещания не стоят того?

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

1 Ответ

0 голосов
/ 06 ноября 2019

Хорошо, я думаю, что вижу, что вы пытаетесь сделать. Проблема заключается в том, что вам нужно собирать комментарии вместе с пользователями, чтобы вы могли затем вернуться вместе и затем объединить их. Это должно выглядеть примерно так:

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

Преобразования: [Комментарий] -> [Пользователь] -> ([Комментарий], [Пользователь]) -> [Комментарии с прикрепленными пользователями]

...