【发布时间】:2020-05-04 19:11:16
【问题描述】:
在搜索了一些关于 Combine 的不同资源(包括 Joseph Heck 和 Donny Wals 的书籍)之后,我接近理解 DataTaskPublishers 的链接,但未能将它们连接到一系列链接的运算符中。我似乎对第一个发布者的输出之间的错误与第二个发布者的预期输入不匹配这一事实感到困惑。两个 Publisher 扩展在未连接时都可以工作,所以我确信它缺乏加入两者的能力。我原以为 mapError() 会起作用,但它不想编译。
设置如下:
给定两个自定义发布者:
extension Publisher where Output == MKCoordinateRegion, Failure == URLError {
func toRegionDataTask() -> AnyPublisher<URLSession.DataTaskPublisher.Output, URLError> {
return self
.flatMap({ region -> URLSession.DataTaskPublisher in
...
...
...
return URLSession.shared.dataTaskPublisher(for: request)
})
.eraseToAnyPublisher()
}
}
和
extension Publisher where Output == [String], Failure == Never {
func toGeographiesDataTask() -> AnyPublisher<URLSession.DataTaskPublisher.Output, URLError {
return self
.setFailureType(to: URLError.self)
.flatMap({ ids -> URLSession.DataTaskPublisher in
...
...
...
return URLSession.shared.dataTaskPublisher(for: request)
})
.eraseToAnyPublisher()
}
}
然后我有一个函数尝试像这样将两者链接在一起:
let passthroughSubj = PassthroughSubject<MKCoordinateRegion,URLError>()
passthroughSubj
.toRegionDataTask() // returns <DataTaskPublisher, URLError>
.map { $0.data } // returns <FlatMap, ?>
.decode(type: ApiResponse.self, decoder:JSONDecoder()) // returns <ApiResonse, ?>
.map {$0.body.data(using: .utf8)! } // returns <Data, ?>
.decode(type: AmznResponse.self, decoder: JSONDecoder()) // returns <AmznResponse, ?>
.map ({ response -> [AmznItem] in //
return response.contents // returns <[AmznItem], ?>
})
.map ({ items -> [String] in // returns <[String], Never> ?
var ids = [String]()
for item in items {
ids.append(item.geoid)
}
return ids
})
//
// .toGeographiesDataTask() // get error "Referencing instance method
// .map { $0.data } // 'toGeographiesDataTask()' on 'Publisher'
// .decode(type: ApiResponse.self, decoder:JSONDecoder()) // requires the types 'Error' and 'Never'
// .map {$0.body.data(using: .utf8)! } // be equivalent"
// .decode(type: AmznResponse.self, decoder: JSONDecoder())
// .map { $0.contents }
//
.sink(receiveCompletion: { (completion) in
switch completion {
case .failure(let error):
print(error)
case .finished:
print("DONE")
}
}, receiveValue: { data in
print(data)
})
.store(in: &cancellables)
passthroughSubj.send(region1)
如果我取消注释第二个自定义发布者,我会收到右侧显示的错误消息。我的理解是 .map 返回 但最终因为 DataTaskPublisher 可能失败,我需要将其映射到 URLError 。但是 .mapError 的组合似乎也无法编译。
我在这里遗漏了一些基本的东西吗?似乎是一个容易解决的问题,但我没有发现任何问题。
我已经看到了使用 .flatMap 将它们链接在一起的示例,但是因为我将其中一个的输出转换为第二个自定义发布者的输入,这似乎是不可能的。
非常欢迎任何帮助或指点!谢谢。
【问题讨论】:
标签: combine