英文:
Make a sequence of 2 requests with Combine in Swift?
问题
我有以下的代码:
import Combine
func login() -> Future<Token, Error> { ... }
func updateImage() -> Future<Status, Never> { ... }
login()
.flatMap { response -> Future<Status, Error> in
// 处理响应并在本地保存令牌
return updateImage()
}
.sink(receiveCompletion: { error in
... // 处理错误
}, receiveValue: { response in
... // 处理响应和不同的错误
})
.store(in: ...)
我想要将 login()
和 updateImage()
连接成一个序列。但是,我发现 zip
只适用于并行请求。我需要一种方法来按顺序链接它们,我不确定 map
、tryMap
或 mapError
方法是否能帮助我实现这一点。我不仅需要转换,还需要处理每个函数的响应数据和错误。
如何解决这个问题?
英文:
I have the following code:
import Combine
func login() -> Future<Token, Error> { ... }
func updateImage() -> Future<Status, Never> { ... }
login()
.flatMap { response -> Future<Status, Error> in
// handle response and save token locally
return updateImage()
}
.sink(receiveCompletion: { error in
... //handleError
}, receiveValue: { response in
... // handle response and a different error
})
.store(in: ...)
I want to join login()
and updateImage()
into a sequence. However, I found that zip
is only for parallel requests. I need a way to chain them sequentially, and I am not sure if map
, tryMap
, or mapError
methods can help me achieve that. I need to not only transform but also handle the response data and errors from each function.
How to solve this issue?
答案1
得分: 1
在iOS 14+中,有一个新的flatMap
重载,允许您将其平坦映射到一个永不失败的发布者,因此您只需更改闭包的显式返回类型以匹配updateImage
返回的类型:
.flatMap { response -> Future<Status, Never> in // 将 "Error" 更改为 "Never"
在iOS 14之前,您需要使用setFailureType(to:)
:
.flatMap { response -> Publishers.SetFailureType<Future<Status, Never>, Error> in
// ...
return updateImage().setFailureType(to: Error.self)
}
如果您不喜欢这样的长类型名称,请使用AnyPublisher
:
.flatMap { response -> AnyPublisher<Status, Error> in
// ...
return updateImage().setFailureType(to: Error.self).eraseToAnyPublisher()
}
英文:
In iOS 14+, there is a new overload of flatMap
that allows you flat map to a publisher that Never
fails, so you just need to change the explicit return type of your closure to match the type that updateImage
returns:
.flatMap { response -> Future<Status, Never> in // change "Error" to "Never"
Prior to iOS 14, you would need to use setFailureType(to:)
:
.flatMap { response -> Publishers.SetFailureType<Future<Status, Never>, Error> in
// ...
return updateImage().setFailureType(to: Error.self)
}
If you don't like such a long type name, use AnyPublisher
:
.flatMap { response -> AnyPublisher<Status, Error> in
// ...
return updateImage().setFailureType(to: Error.self).eraseToAnyPublisher()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论