如何妥善处理所有潜在的网络错误?
How Can I Handle All Potential Network Errors Appropriately?
我有一个网络管理器 class 负责与我们服务的后端进行所有通信。当网络请求可能失败时,我一心想为用户提供良好的体验。
现在,网络管理员 class 发出请求以向后端进行身份验证:
internal func authenticate(withEmailAddress emailAddress: String, andPassword password: String, withCompletion completion: @escaping (Result<Data>) -> Void) {
// ...Create the request...
task = session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
if let requestError = error as? NSError {
// ...Handle CFNetworkErrors (-1001, etc.)...
}
if let httpResponse = response as? HTTPURLResponse {
// ...Handle the response codes (200, 400, 401, 500)...
} else {
// ...Handle the response not being of type `HTTPURLResponse`...
}
})
// ...Start the task...
}
我有另一个 class 管理完成处理程序的 Data
或 Error
的 return,它基于响应的状态代码或请求的错误。
看了 list of HTTP status codes and a list of CFNetworkErrors 之后,我发现有 很多 的可能性来处理此类错误。我意识到并非所有 CFNetworkErrors
都适用于我的情况,但我仍然需要处理一长串错误。
除了打开 requestError.code
之外,是否有我应该采取的处理可能错误的方向?
如果我要处理所有 CFNetworkErrors
,那么我最终会得到一个很长的逻辑块来检查这样的代码:
switch code {
case -1005: // ...Handle error...
case -1001: // ...Handle error...
case 1: // ...Handle error...
case 200: // ...Handle error...
// ...Handle the rest of the errors...
default: // ...Handle error...
}
我最终也会得到一个很长的块来处理所有适当的响应状态代码,如下所示:
switch response.statusCode {
case 200: // ...Do something with data...
case 400: // ...Handle missing user credentials...
case 401: // ...Handle incorrect credentials...
case 500: // ...Handle internal server error...
// ...Handle the rest of the status codes...
default: // ...Handle default error...
}
在尝试处理可能遇到的所有网络错误时,您能否就一些好的做法提供一些指导?
首先,我认为专门处理所有可能的网络错误是非常困难的。有很多,正如您已经知道的,所以让它更通用一些来处理状态组会容易得多。您可以在您的案例语句中使用范围运算符,如下所示:
switch response.statusCode {
case 200...299: // ...Do something with data...
case 300...399: // ...Handle redirect...
case 400...499: // ...Handle client error...
case 500...599: // ...Handle server error...
default: // ...Handle default error...
}
您甚至可以在其中添加您想要处理的特定情况——例如,您可能希望以非常具体的方式处理 401 Unauthorized,或许通知用户——这样您就可以将其添加到您的将 switch 语句作为它自己的 case 并调用您要将问题通知用户的代码。
我有一个网络管理器 class 负责与我们服务的后端进行所有通信。当网络请求可能失败时,我一心想为用户提供良好的体验。
现在,网络管理员 class 发出请求以向后端进行身份验证:
internal func authenticate(withEmailAddress emailAddress: String, andPassword password: String, withCompletion completion: @escaping (Result<Data>) -> Void) {
// ...Create the request...
task = session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
if let requestError = error as? NSError {
// ...Handle CFNetworkErrors (-1001, etc.)...
}
if let httpResponse = response as? HTTPURLResponse {
// ...Handle the response codes (200, 400, 401, 500)...
} else {
// ...Handle the response not being of type `HTTPURLResponse`...
}
})
// ...Start the task...
}
我有另一个 class 管理完成处理程序的 Data
或 Error
的 return,它基于响应的状态代码或请求的错误。
看了 list of HTTP status codes and a list of CFNetworkErrors 之后,我发现有 很多 的可能性来处理此类错误。我意识到并非所有 CFNetworkErrors
都适用于我的情况,但我仍然需要处理一长串错误。
除了打开 requestError.code
之外,是否有我应该采取的处理可能错误的方向?
如果我要处理所有 CFNetworkErrors
,那么我最终会得到一个很长的逻辑块来检查这样的代码:
switch code {
case -1005: // ...Handle error...
case -1001: // ...Handle error...
case 1: // ...Handle error...
case 200: // ...Handle error...
// ...Handle the rest of the errors...
default: // ...Handle error...
}
我最终也会得到一个很长的块来处理所有适当的响应状态代码,如下所示:
switch response.statusCode {
case 200: // ...Do something with data...
case 400: // ...Handle missing user credentials...
case 401: // ...Handle incorrect credentials...
case 500: // ...Handle internal server error...
// ...Handle the rest of the status codes...
default: // ...Handle default error...
}
在尝试处理可能遇到的所有网络错误时,您能否就一些好的做法提供一些指导?
首先,我认为专门处理所有可能的网络错误是非常困难的。有很多,正如您已经知道的,所以让它更通用一些来处理状态组会容易得多。您可以在您的案例语句中使用范围运算符,如下所示:
switch response.statusCode {
case 200...299: // ...Do something with data...
case 300...399: // ...Handle redirect...
case 400...499: // ...Handle client error...
case 500...599: // ...Handle server error...
default: // ...Handle default error...
}
您甚至可以在其中添加您想要处理的特定情况——例如,您可能希望以非常具体的方式处理 401 Unauthorized,或许通知用户——这样您就可以将其添加到您的将 switch 语句作为它自己的 case 并调用您要将问题通知用户的代码。