Network programming 发布服务器出现故障时,联合收割机接收器未完成
我目前正在构建一个SwiftUI应用程序,并使用github()中的一个网络库来实现api调用 它工作正常,除非请求失败,然后库内部调试消息指示错误(在我的测试中为404),但联合收割机订户从未收到完成信号 我创建了一个新请求,它将尝试获取并解码“jsonplaceholder.typicode.com”的用户 用户只是一个简单的结构:Network programming 发布服务器出现故障时,联合收割机接收器未完成,network-programming,swiftui,combine,Network Programming,Swiftui,Combine,我目前正在构建一个SwiftUI应用程序,并使用github()中的一个网络库来实现api调用 它工作正常,除非请求失败,然后库内部调试消息指示错误(在我的测试中为404),但联合收割机订户从未收到完成信号 我创建了一个新请求,它将尝试获取并解码“jsonplaceholder.typicode.com”的用户 用户只是一个简单的结构: struct User: Decodable { let id: Int let username: String let name:
struct User: Decodable {
let id: Int
let username: String
let name: String
}
在我的ApiRequestManager.swift文件中,我声明了一个请求调度的函数:
public func getUsersFromMockApi() -> Response<GetUsersFromMockApiRequest> {
return GetUsersFromMockApiRequest().schedule(with: ApiService(apiUrl: "jsonplaceholder.typicode.com"))
}
如果api请求成功,则一切正常。但一旦出现任何错误,接收器将收到任何信号/完成
我试着打印订阅者收到的每一条消息,并且一步一步地跟踪库,看看他是否抛出了一个错误。它会根据NetworkScheduler.swift文件中schedule()函数中接受的状态代码正确检查HTTP响应代码,并在第285行抛出一个自定义错误throw Squid.error.requestFailed(状态代码:状态代码,响应:response.data)
然而,由于我缺乏调试和组合知识,我很难在之后的测试中完成 您看到的问题可能是404不被底层Cocoa库(特别是URLSession)视为错误。这看起来像是Squid库中正在做(或不做)的事情,您正在对它提供的内容做出反应 URLSession本身只有在无法从服务器获得响应时才会抛出错误——因此,当问题与无法解析主机名或建立连接之类的事情有关时。如果您确实建立了连接并得到了响应,URLSession不会抛出错误,但状态代码会正确反映出来——它看起来就像是一个成功的请求 上面的示例没有显示该部分,但是来自
URLSession
的404响应发生的情况是请求完成,并且状态代码404
在响应中编码,但不会作为错误状态抛出
在联合发布器链中处理此问题的典型模式是将结果数据从URLSession传递到tryMap
操作符,在该操作符中,您可以进一步检查结果(状态代码、数据等),并确定是否要将其转化为抛出的错误(例如,如果收到404响应)
你可以在网站上找到这种模式的一个例子。此模式的要点是允许您基于对结果的检查定义任何您想要的错误(假设在这些情况下引发了异常)
您可以在中找到使用Combine(以及
URLSession.dataTaskPublisher
)的其他示例。您看到的问题可能是404不被底层Cocoa库(特别是URLSession)视为错误。这看起来像是Squid库中正在做(或不做)的事情,您正在对它提供的内容做出反应
URLSession本身只有在无法从服务器获得响应时才会抛出错误——因此,当问题与无法解析主机名或建立连接之类的事情有关时。如果您确实建立了连接并得到了响应,URLSession不会抛出错误,但状态代码会正确反映出来——它看起来就像是一个成功的请求
上面的示例没有显示该部分,但是来自URLSession
的404响应发生的情况是请求完成,并且状态代码404
在响应中编码,但不会作为错误状态抛出
在联合发布器链中处理此问题的典型模式是将结果数据从URLSession传递到tryMap
操作符,在该操作符中,您可以进一步检查结果(状态代码、数据等),并确定是否要将其转化为抛出的错误(例如,如果收到404响应)
你可以在网站上找到这种模式的一个例子。此模式的要点是允许您基于对结果的检查定义任何您想要的错误(假设在这些情况下引发了异常)
您可以在中找到其他使用Combine(以及
URLSession.dataTaskPublisher
)的示例。非常有洞察力,是的,这就是问题所在。我联系了图书馆的开发人员,他似乎只是错过了404案例。他很快就修好了,现在一切都正常了!谢谢你的帮助。很有洞察力,是的,这就是问题所在。我联系了图书馆的开发人员,他似乎只是错过了404案例。他很快就修好了,现在一切都正常了!谢谢你的帮助。
public func getUsersFromMockApi() -> Response<GetUsersFromMockApiRequest> {
return GetUsersFromMockApiRequest().schedule(with: ApiService(apiUrl: "jsonplaceholder.typicode.com"))
}
@State private var cancellableSet: Set<AnyCancellable> = []
private let requestManager = ApiRequestManager()
self.requestManager.getUsersFromMockApi()
.print("Debug:")
.sink(receiveCompletion: { completion in
switch completion {
case .failure:
print("ApiCall failed.")
case .finished:
print("ApiCall finished.")
}
}) { result in
print("Received users from apiCall: \(result)")
}
.store(in: &cancellableSet)