PromiseKit 6:如何创建多个并发承诺并将其各自的结果分组到一个数组中?

PromiseKit 6: How to create multiple concurrent promises and group their individual results into an array?

我正在处理一个奇怪的 API,我收到了一个 ID 列表,我需要分别请求每个 ID 的数据。我不需要一个接一个地链接这些请求,我只想一次获取所有请求,但我无法弄清楚如何以干净的方式执行此操作。

我已经制作了获取一个ID的方法,它产生了一个Promise<DataObject>。我如何将我的 ID 数组变成一组承诺,然后给我 [DataObject]

func fetchDataObject(_ id: Int64) -> Promise<DataObject> {
    return makeURL("\(id)")
        .then {
            URLSession.shared.dataTask(.promise, with: [=10=])
        }.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: [=10=])
        }.compactMap { (data, response) -> [Int64] in
            // ...
            return try decoder.decode([Int64].self, from: data)
        }.then({ (ids) -> [DataObject] in
            // now what???
        })
}

我想我应该使用 .when 但我找不到明确选择哪个方法签名...以及如何创建要传入的承诺数组。

好的,我找到了有用的东西,现在我更好地理解 thenwhen(fulfilled:)

您需要 return 您 then 中的 when

func fetchObjects() -> Promise<[DataObject]> {
    return makeURL("all_ids")
        .then {
            URLSession.shared.dataTask(.promise, with: [=10=])
        }.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)
    }
}

这是您的答案,但根据要求“更清洁”。

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

关键的变化是 thenMap 对序列的每个元素应用承诺 returning a Promise<[T]>.

还使用 Swift 单行闭包语法删除 return 和参数名称,它们不会增加太多价值。

firstly阅读链条更清晰

URLSession 上使用 validate() 承诺如果 HTTP return 是非 2xx 响应则拒绝链。

compactMap 替换为 map 因为 decode() 不是 return 可选项。