为什么我不能在 Swift Combine 中的 .tryMap() 之后使用 .flatMap()?
Why can't I use .flatMap() after .tryMap() in Swift Combine?
我正在研究并尝试使用 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: [=11=].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)
我有一个发出 3 个整数的序列发布器,我通过 flatMap
传递它并向我的本地 API 发送一个 Get 请求请求,它只是 returns 返回相同的值嵌入字符串中。
一切正常,我在接收器中得到了所有 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
}
}
}
如果我在 flatMap 工作之前添加另一个 map
运算符,代码甚至不会编译,但是对于 tryMap 它只是说
No exact matches in call to instance method 'flatMap'
是否有任何方法可以实现此目的或为什么不允许这样做?
提前感谢您的回答
这里的问题是 FlatMap
要求在其闭包中创建的返回发布者与其上游具有相同的 Failure
类型(除非上游发生 Never
故障)。
因此,Sequence
发布商,例如:
let sequencePublisher = [70, 5, 17].publisher
故障类型为 Never
,并且一切正常。
但是 TryMap
,也就是 .spellOut
运算符 returns,有一个失败类型 Error
,所以它失败了,因为 DataTaskPublisher
有URLError
故障类型。
一种修复方法是匹配 flatMap
:
中的错误类型
sequencePublisher
.spellOut()
.flatMap { query in
URLSession.shared.dataTaskPublisher(for: URL(...))
.mapError { [=11=] as Error }
}
// etc...
我正在研究并尝试使用 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: [=11=].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)
我有一个发出 3 个整数的序列发布器,我通过 flatMap
传递它并向我的本地 API 发送一个 Get 请求请求,它只是 returns 返回相同的值嵌入字符串中。
一切正常,我在接收器中得到了所有 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
}
}
}
如果我在 flatMap 工作之前添加另一个 map
运算符,代码甚至不会编译,但是对于 tryMap 它只是说
No exact matches in call to instance method 'flatMap'
是否有任何方法可以实现此目的或为什么不允许这样做?
提前感谢您的回答
这里的问题是 FlatMap
要求在其闭包中创建的返回发布者与其上游具有相同的 Failure
类型(除非上游发生 Never
故障)。
因此,Sequence
发布商,例如:
let sequencePublisher = [70, 5, 17].publisher
故障类型为 Never
,并且一切正常。
但是 TryMap
,也就是 .spellOut
运算符 returns,有一个失败类型 Error
,所以它失败了,因为 DataTaskPublisher
有URLError
故障类型。
一种修复方法是匹配 flatMap
:
sequencePublisher
.spellOut()
.flatMap { query in
URLSession.shared.dataTaskPublisher(for: URL(...))
.mapError { [=11=] as Error }
}
// etc...