【问题标题】:Deal with concurrent http requests that depend on each other处理相互依赖的并发http请求
【发布时间】:2018-02-17 02:53:33
【问题描述】:

所以,我有一个复杂的数据要获取,其中涉及 4 个请求,每个请求取决于最后一个的结果,然后其中一些返回一个列表,因此对于该列表中的每个元素,我必须获取一些信息.

上下文

我正在使用 YouTube API,我必须获取的数据是用户订阅频道发送的最新视频列表。

以下是执行此操作所需的请求:

  • GET /subscriptions/list [1]

  • GET /channels/list [2]

  • GET /playlistItems/list [3]

  • 获取 /videos [4]

[1]:返回用户订阅频道的列表。返回大小配置为5,所以我必须重复这个请求,直到所有订阅的频道都被获取

[2]:返回特定频道的已发送视频播放列表的 id

[3]:返回特定频道的最后 n 个视频

[4]:返回特定视频的信息

第一次尝试

一开始我是通过同步的方式获取数据,也就是执行request[1],直到所有channel都获取完毕。然后,我遍历频道列表,并为每个频道执行请求 [2] 以获取播放列表的 id。然后请求 [3] 获取 n 个视频,对于每个视频,通过请求 [4] 获取其信息。

问题

问题在于将视频返回给用户需要很长时间,所以我想到了并行执行请求。问题是我需要知道所有请求何时完成运行,以便按日期重新排序视频列表。为了做到这一点,我的代码变成了 DispatchGroup 的乱七八糟的乱七八糟的东西。

所以,简而言之,什么是处理这样的问题的最佳方法,我有各种相互依赖的请求,我想执行其中一些并行(第二个 - 我必须为每个通道执行)并且需要知道何时完成。

【问题讨论】:

  • 显示你到目前为止所做的事情。

标签: swift concurrency nsurlsession


【解决方案1】:

使用DispatchGroup。 DispatchGroup是iOS中的一个“组件”,可以对一些相关的操作进行分组,必须等待。

这里不能直接使用,为什么?因为 URLSession 本身将 web 操作发布在与发起者不同的后台线程上,所以我们必须手动 enterleave。当操作计数为 0 时,group.wait 返回。

这段代码不是最好的设计模式。但这只是演示了在简单的设计模式中可以做什么。

import UIKit

class URLRequestGroup {

    var dispatchGroup: DispatchGroup

    init(dispatchGroup: DispatchGroup) {
        self.dispatchGroup = dispatchGroup
    }

    init() {
        self.dispatchGroup = DispatchGroup()
    }

    func beginURLRequest(urlRequest: URLRequest,
                         completionHandler: @escaping (Data?, URLResponse?, Error?) -> ()) {

        let urlSession = URLSession(configuration: URLSessionConfiguration.default)
        // Enter the dispatchGroup manually
        dispatchGroup.enter()
        urlSession.dataTask(with: urlRequest, completionHandler: { [weak self] data, urlResponse, error in

            completionHandler(data, urlResponse, error)
            // Leave this dispatchGroup.
            self?.dispatchGroup.leave()
        }).resume()

    }

}

let group = URLRequestGroup()
group.beginURLRequest(urlRequest: URLRequest(url: URL(fileURLWithPath: "http://www.example.com")), completionHandler: { data, urlResponse, error in

    print(data?.count ?? 0)
})
// Put any other request here.
group.dispatchGroup.wait()

【讨论】:

  • 是的,但我想不出使用这种方法轻松组织请求的方法。现在我正在尝试使用Just 来隐藏一些 URLSession 复杂性,并混合它的同步/异步操作模式。看起来代码越来越容易使用了......我稍后会在这里发布结果。
  • 这种方法有什么难点?只需1.创建一个DispatchGroup,2.初始化请求时,使用dispatchGroup.enter(),3.当请求结束或出错时,使用dispatchGroup.leave()。就是这样。
  • 问题是我必须执行的请求数才能获得所需的数据。每个请求都取决于前一个请求。我尝试构建的方式,它变成了一团糟的回调来管理。
【解决方案2】:

所以,我正在努力尝试使用 NSURLSession 组织这个复杂的请求过程,但我无法找到我想要的代码。

为了更容易使用,我使用了Just,它让我能够以更简单、更清晰、更轻松的方式执行这些请求。

另一种选择是使用PromiseKitNSURLSession 包装在一个promise 上,这很容易允许chaining of requests

【讨论】:

    猜你喜欢
    • 2015-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 2014-09-08
    • 2021-12-03
    • 1970-01-01
    相关资源
    最近更新 更多