【发布时间】:2021-07-16 05:14:55
【问题描述】:
我们应该改用什么?
我很惊讶以前没有人问过这个问题。
【问题讨论】:
-
至于
why,只有苹果才能回答。至于替代方案,我认为没有内置运算符可以将 1-1 映射到tryFlatMap之类的东西,因此您需要实现自己的Operator。 -
这是个好问题。我假设它因为缺少代码示例而被否决?
我们应该改用什么?
我很惊讶以前没有人问过这个问题。
【问题讨论】:
why,只有苹果才能回答。至于替代方案,我认为没有内置运算符可以将 1-1 映射到 tryFlatMap 之类的东西,因此您需要实现自己的 Operator。
您并不严格需要tryFlatMap,因为flatMap 的转换返回一个发布者。您可以在转换闭包中使用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>(
maxPublishers: Subscribers.Demand = .unlimited,
_ transform: @escaping (Output) throws -> Pub
) -> Publishers.FlatMap<AnyPublisher<Pub.Output, Error>, Self> {
return flatMap(maxPublishers: maxPublishers, { 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。
例如。
整个故事开始于我只是想打开一个可选的。如果它为零,我希望它只是失败。
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()
错误类型有点烦人。
【讨论】: