我正在研究并尝试使用Combine 自己应用一些东西,并通过这个人为的示例遇到了以下情况。
let sequencePublisher = [70, 5, 17].publisher
var cancellables = [AnyCancellable]()
sequencePublisher
// .spellOut()
.flatMap { query -> URLSession.DataTaskPublisher in
return URLSession.shared.dataTaskPublisher(for: URL(string: "http://localhost:3000?q=\(query)")!)
}
.compactMap { String(data: $0.data, encoding: .utf8) }
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
print(error.localizedDescription)
default: print("finish")
}
}) { value in
print(value)
}
.store(in: &cancellables)
Run Code Online (Sandbox Code Playgroud)
我有一个发出 3 个整数的序列发布者,我将其传递flatMap并向我的本地 API 发送一个 Get 请求,该 API 只是返回嵌入在字符串中的相同值。
一切正常,我在接收器中得到了所有 3 个 API 响应,只要我不取消注释spellOut()自定义运算符,如果数字小于 6,则该运算符应该会失败,这是它的作用:
enum ConversionError: LocalizedError {
case lessThanSix(Int)
var errorDescription: String? {
switch self {
case .lessThanSix(let n):
return "could not convert number -> \(n)"
}
}
}
extension Publisher where Output == Int {
func spellOut() -> Publishers.TryMap<Self, String> {
tryMap { n -> String in
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
guard n > 6, let spelledOut = formatter.string(from: n as NSNumber) else { throw ConversionError.lessThanSix(n) }
return spelledOut
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我在 flatMap 工作之前添加另一个运算符,代码甚至无法编译map,但使用 tryMap 它只是说
对实例方法“flatMap”的调用没有完全匹配
有什么方法可以实现这一点或者为什么不允许这样做?
预先感谢您的答复
这里的问题是,FlatMap要求在其闭包中创建的返回发布者与其上游具有相同的Failure类型(除非上游出现Never故障)。
所以,Sequence出版商,比如:
let sequencePublisher = [70, 5, 17].publisher
Run Code Online (Sandbox Code Playgroud)
故障类型为Never且全部有效。
但是TryMap,即.spellOut运算符返回的内容,具有 的失败类型Error,因此它会失败,因为DataTaskPublisher有一个URLError失败类型。
修复方法是匹配以下内容中的错误类型flatMap:
sequencePublisher
.spellOut()
.flatMap { query in
URLSession.shared.dataTaskPublisher(for: URL(...))
.mapError { $0 as Error }
}
// etc...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4039 次 |
| 最近记录: |