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
但我找不到明确选择哪个方法签名...以及如何创建要传入的承诺数组。
好的,我找到了有用的东西,现在我更好地理解 then
和 when(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 可选项。
我正在处理一个奇怪的 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
但我找不到明确选择哪个方法签名...以及如何创建要传入的承诺数组。
好的,我找到了有用的东西,现在我更好地理解 then
和 when(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 可选项。