【发布时间】:2021-11-22 08:44:36
【问题描述】:
我有一个流程,我应该从 Web 获取帖子,并将它们保存在用户默认值上作为测试,如果有问题,从用户默认值而不是 Web 加载列表。现在我有两个发射器,我想我应该在我的存储库中执行检查,例如如果门柱发出错误,则决定显示本地缓存的帖子。如何捕捉错误?他们告诉我我可以使用 combine latest 或 mergeMany 但我是全新的,不知道如何执行此检查
我有这个提示,但不起作用
dataSource.getPosts().catch {sharedPreferenceDataSource.getLocalPosts()}
这似乎有效,但仍然没有出错或使用最新的组合
return dataSource.getPosts().catch { error in
return self.sharedPreferenceDataSource.getLocalPosts()
}.eraseToAnyPublisher()
我的功能
func getPosts() -> AnyPublisher<[Post], Error> {
//posts from web
dataSource.getPosts() //emits AnyPublisher<[Post], Error>
//posts on usersDeafault
sharedPreferenceDataSource.getLocalPosts() //emits AnyPublisher<[Post], Error>
//here someone told me I should perform a catch,I get something likeMyEnumeError.networkError, then I should emit local posts
//my latest attempt
return Publishers.CombineLatest(dataSource.getPosts(), sharedPreferenceDataSource.getLocalPosts())
// but I think I could do something like
// perform a catch on the error from network, in that case perform a catch and send local data
// Publishers.MergeMany([dataSource.getPosts(),dataSource.getLocalPosts(defaults: defaults, key: UserDefaultKeys.allPost.rawValue)])
}
我的电话
enum NetworkError: Error {
case genericError(code: Int)
case invalidResponseCode
case decodingFailure(reason: String)
}
func getPosts() -> AnyPublisher<[Post], Error> {
let session = URLSession.shared
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
return Future<[Post], Error>() { promise in
//***********************************************
let task = session.dataTask(with: url, completionHandler: { data, response, error in
if error != nil {
print(error ?? "N/D")
promise(Result.failure(NetworkError.invalidResponseCode))
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
promise(Result.failure(NetworkError.invalidResponseCode))
return
}
do {
let posts = try JSONDecoder().decode([Post].self, from: data! )
promise(Result.success(posts))
//saving on local disk
self.saveLocalPosts(defaults: self.defaults, data: AllPosts(Posts: posts))
} catch {
print("Error during JSON serialization: \(error.localizedDescription)")
promise(Result.failure(NetworkError.decodingFailure(reason: error.localizedDescription)))
}
})
task.resume()
//***********************************************
}
// .receive(on: DispatchQueue.main)
// .subscribe(on: DispatchQueue.init(label: "test", qos: .default))
// .map { value -> [Post] in
// let c = value
// return []
// }
.eraseToAnyPublisher()
}
【问题讨论】:
-
CombineLatest运算符结合了两个独立的源。但在您的示例中,本地任务取决于远程任务的输出。所以map或flatMap可能更合适。 -
嗨,瓦迪安!起初我需要使用 combineLatest 和/或使用我现在添加到问题中的“提示”,问题是如何使用该提示执行错误检查
-
更准确地说,使用
tryMap运算符能够捕获错误。 -
如果我尝试使用 catch 或 tryMap 我无论如何都无法获得错误类型,例如使用开关。
标签: swift combine combinelatest