为什么我们在Combine中没有tryFlatMap操作符?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么我们在Combine中没有tryFlatMap操作符?相关的知识,希望对你有一定的参考价值。
我们应该用什么来代替呢?我很惊讶以前没有人问过这个问题。
答案
因为 flatMap
的transform返回一个发布者,你不需要严格地使用 tryFlatMap
. 您可以使用 do/catch
并返回一个 Fail
如果你发现了错误,可以向出版商咨询。
import Combine
func someFunction(of i: Int) throws -> AnyPublisher<Int, Error> {
return Just(i + 1)
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
}
let upstream: AnyPublisher<Int, Error> = Just(100)
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
upstream
.flatMap({ i -> AnyPublisher<Int, Error> in
do {
return try someFunction(of: i).eraseToAnyPublisher()
} catch {
return Fail(error: error).eraseToAnyPublisher()
}
})
你可以写你自己的 tryFlatMap
如果你喜欢的话,操作者。
extension Publisher {
func tryFlatMap<Pub: Publisher>(
_ transform: @escaping (Output) throws -> Pub
) -> Publishers.FlatMap<AnyPublisher<Pub.Output, Error>, Self> {
return flatMap({ input -> AnyPublisher<Pub.Output, Error> in
do {
return try transform(input)
.mapError { $0 as Error }
.eraseToAnyPublisher()
} catch {
return Fail(outputType: Pub.Output.self, failure: error)
.eraseToAnyPublisher()
}
})
}
}
然后像这样使用它
upstream
.tryFlatMap { try someFunction(of: $0) }
另一答案
还有一个解决方案 tryFlatMap = tryMap + flatMap.
举个例子。整个故事的开始,我只是想解开一个可选的。而如果它是nil,我希望它只是失败。
let upstream = Just(siteURL)
.tryMap { url -> URL in
guard let url = url else { throw Errors.invalidSiteURL }
return url
}
.flatMap {
URLSession.shared.dataTaskPublisher(for: $0).mapError { $0 as Error }
}
编辑】像这样也可以。
let container = Just(siteURL)
.tryMap { url -> URLSession.DataTaskPublisher in
guard let url = url else { throw Errors.invalidSiteURL }
return URLSession.shared.dataTaskPublisher(for: url)
}
.map { $0.mapError { $0 as Error } }
.switchToLatest()
乱用错误类型有点烦人。
以上是关于为什么我们在Combine中没有tryFlatMap操作符?的主要内容,如果未能解决你的问题,请参考以下文章
Combine 的 receive(on:) 没有分派到串行队列,导致数据竞争