代码之家  ›  专栏  ›  技术社区  ›  ray

PromiseKit6:如何创建多个并发承诺,并将它们各自的结果分组到一个数组中?

  •  0
  • ray  · 技术社区  · 6 年前

    我正在处理一个奇怪的API,在这里我收到一个id列表,我需要分别请求每个id上的数据。我不需要一个接一个地链接这些请求,我只想一次抓住它们,但我很难弄清楚如何以一种干净的方式完成这些请求。

    我已经做了一个获取一个ID的方法,它会产生一个 Promise<DataObject> . 我该如何将我的ID数组转换成一个承诺集合,然后给我 [DataObject]

    func fetchDataObject(_ id: Int64) -> Promise<DataObject> {
        return makeURL("\(id)")
            .then {
                URLSession.shared.dataTask(.promise, with: $0)
            }.compactMap { (data, response) -> DataObject in
                // ...
                return try decoder.decode(DataObject.self, from: data)
        }
    }
    
    // get the list of IDs and turn them into DataObjects
    
    func fetchNew() -> Promise<[DataObject]> { // desired output
        return makeURL("all_ids").then {
            URLSession.shared.dataTask(.promise, with: $0)
            }.compactMap { (data, response) -> [Int64] in
                // ...
                return try decoder.decode([Int64].self, from: data)
            }.then({ (ids) -> [DataObject] in
                // now what???
            })
    }
    

    我想我应该用 .when 但我找不到一个明确的选择哪种方法签名。。。以及如何创造一系列承诺来传递。

    2 回复  |  直到 6 年前
        1
  •  5
  •   mxcl    6 年前

    这是你的答案,但按要求。

    func fetchObjects() -> Promise<[DataObject]> {
        return firstly {
            makeURL("all_ids")
        }.then {
            URLSession.shared.dataTask(.promise, with: $0).validate()
        }.map {
            try decoder.decode([Int64].self, from: $0.data)
        }.thenMap {
            self.fetchDataObject($0)
        }
    }
    

    关键的变化是 thenMap Promise<[T]> .

    firstly 使阅读链更清晰。

    使用 validate() URLSession 如果HTTP返回非2xx响应,则承诺拒绝链。

    compactMap 具有 map decode()

        2
  •  0
  •   ray    6 年前

    then when(fulfilled:) 现在。

    when 在你的 .

    func fetchObjects() -> Promise<[DataObject]> {
        return makeURL("all_ids")
            .then {
                URLSession.shared.dataTask(.promise, with: $0)
            }.compactMap { (data, response) -> [Int64] in
                // ..
                return try decoder.decode([Int64].self, from: data)
            }.then { (ids) -> Promise<[DataObject]> in
                var requests: [Promise<DataObject>] = []
                for id in ids {
                    requests.append(self.fetchDataObject(id))
                }
                return when(fulfilled: requests)
        }
    }