繁体   English   中英

重试 URLSession dataTask 的模式?

[英]Pattern for retrying URLSession dataTask?

我对 iOS/Swift 开发还很陌生,我正在开发一个向 REST API 发出多个请求的应用程序。 这是检索“消息”的其中一个调用的示例:

func getMessages() {

    let endpoint = "/api/outgoingMessages"

    let parameters: [String: Any] = [
        "limit" : 100,
        "sortOrder" : "ASC"
    ]

    guard let url = createURLWithComponents(endpoint: endpoint, parameters: parameters) else {
        print("Failed to create URL!")
        return
    }

    do {
        var request = try URLRequest(url: url, method: .get)

        let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in

            if let error = error {
                print("Request failed with error: \(error)")
                // TODO: retry failed request
            } else if let data = data, let response = response as? HTTPURLResponse {                
                if response.statusCode == 200 {
                    // process data here
                } else {
                    // TODO: retry failed request
                }
            }
        }

        task.resume()

    } catch {
        print("Failed to construct URL: \(error)")
    }
}

当然,此请求可能因多种不同原因而失败(服务器无法访问、请求超时、服务器返回 200 以外的其他内容等)。 如果我的请求失败,我希望能够重试它,甚至可能在下一次尝试之前延迟。 我在 Apple 的文档中没有看到关于这种情况的任何指导,但我发现了一些关于 SO 的相关讨论。 不幸的是,这两个都是几年前的,并且在我从未使用过的 Objective-C 中。 在 Swift 中是否有任何常见的模式或实现来做这样的事情?

这个问题是基于意见的一面,而且相当广泛,但我敢打赌大多数是相似的,所以这里是。

对于触发 UI 更改的数据更新:

(例如,填充数据的表或加载图像)一般的经验法则是以无障碍的方式通知用户,如下所示:

然后有一个下拉刷新控件或刷新按钮。

对于不影响用户操作或行为的后台数据更新:

您可以根据代码轻松地将重试计数器添加到您的请求结果中 - 但我会小心使用这个计数器并构建一些更智能的逻辑。 例如,给定以下状态代码,您可能希望以不同的方式处理事情:

  • 5xx:您的服务器有问题。 您可能希望将重试延迟 30 秒或一分钟,但如果发生 3 或 4 次,您将希望停止重试后端。

  • 401:经过身份验证的用户可能不再有权调用您的 API。 你根本不想重试; 相反,您可能希望将用户注销,以便下次他们使用您的应用程序时,系统会提示他们重新进行身份验证。

  • 网络超时/丢失连接:在重新建立连接之前,重试无关紧要。 您可以围绕可达性处理程序编写一些逻辑,以便在下一次网络连接可用时对后台请求进行排队。

最后,正如我们在评论中提到的,您可能想要查看通知驱动的后台应用程序刷新。 在这里,您可以发送通知来告诉应用程序进行自我更新,而不是轮询服务器以获取更改,即使它不在前台运行。 如果您足够聪明,您可以让您的服务器向您的应用程序重复通知,直到应用程序确认收到 - 这以一致的方式解决了连接故障和无数其他服务器响应错误代码。

我将处理重试的三种方法分类:

  1. 可达性重试
  • 可达性是一种说“当网络连接发生变化时让我知道”的奇特方式。 Apple 对此有一些片段,但它们看起来并不有趣——我的建议是使用类似 Ashley Mill 的Reachability替代品。
  • 除了可达性之外,Apple 还提供了一个waitsForConnectivity (iOS 11+) 属性,您可以在URLSession配置上设置该URLSession 通过设置它,当任务正在等待网络连接时,您会通过URLSessionDataDelegate 您可以利用这个机会启用离线模式或向用户显示某些内容。
  1. 手动重试
  • 让用户决定何时重试请求。 我会说这是最常见的使用“拉动刷新”手势/用户界面来实现的。
  1. 定时/自动重试
  • 等待几秒钟,然后重试。
  • Apple 的Combine 框架提供了一种重试失败的网络请求的便捷方法。 请参阅使用组合处理 URL 会话数据任务结果
  • 来自Apple Docs: Life Cycle of a URL Session (deprecated) ... 但是,您的应用不应立即重试 [a request]。 相反,它应该使用可达性 API 来确定服务器是否可达,并且应该仅在收到可达性已更改的通知时才发出新请求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM