【问题标题】:How to make sure that NSURLSession responses are received in same order as requests are made?如何确保收到 NSURLSession 响应的顺序与发出请求的顺序相同?
【发布时间】:2015-08-05 22:29:57
【问题描述】:

我在一个循环中发出几个 NSURLSession 请求。我想以与创建任务相同的顺序存储响应的结果。但由于完成处理程序在单独的线程中运行,有时会发生对第二个任务的响应在对第一个任务的响应之前收到。

如何确保我得到响应的顺序与任务开始的顺序相同?

var recivedData = [String]()

for index in 0 ... urlsAsString.count-1 {
    let myUrl = NSURL(string: urlsAsString[index])
    var request = NSMutableURLRequest(URL: myUrl!)
    // here I also set additional parameters (HTTPMethod, ...)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        responseData, response, error in

         // here I handle the response
         let result = ...
         dispatch_async(dispatch_get_main_queue()) {
             self.recivedData.append("\(result)")   // save the result to array
         }
     }
     task.resume()
}

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    虽然我不鼓励要求以特定顺序接收响应的行为,但您可以将响应(无论接收它们的顺序如何)整理成已知顺序。

    receivedData 数组的初始化容量应与将要发出的请求数相匹配:

    var receivedData = [String](count: urlsAsString.count, repeatedValue: "")
    

    然后当您收到响应时,由于您位于可以访问请求的index 的块中,您可以将响应数据直接添加到receivedData 数组的索引中:

    receivedData[index] = result as (String)
    

    完整代码如下:

    var receivedData = [String](count: urlsAsString.count, repeatedValue: "")
    
    for index in 0 ... urlsAsString.count-1 {
        let myUrl = NSURL(string: urlsAsString[index])
        var request = NSMutableURLRequest(URL: myUrl!)
        // here I also set additional parameters (HTTPMethod, ...)
    
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
                responseData, response, error in
    
            // here I handle the response
            let result = ...
            dispatch_async(dispatch_get_main_queue()) {
                // Insert the result into the correct index
                receivedData[index] = result
            }
        }
        task.resume()
    }
    

    【讨论】:

      【解决方案2】:

      因为您知道确切的 http 请求数。

      您可以创建一个大小为urls.count 的数组,然后在完成处理程序中设置结果,对应每个循环中的索引。

      receivedData = [String](count: urls.count, repeatedValue: "No Data")
      for (index,url) in enumerate(urls){
          let url = NSURL(string: url)!
          let task = NSURLSession.sharedSession().dataTaskWithURL(url){ data, response, error in
              if error != nil{
                  self.receivedData[index] = "error: \(error.localizedDescription)"
                  return
              }
              let result = ...
              dispatch_async(dispatch_get_main_queue()) {
                  self.recivedData[index] = "\(result)"
              }
          }
          task.resume()
      }
      

      【讨论】:

        【解决方案3】:

        实际上,无法确定响应的顺序。 有两种解决方法:

        1. 一个接一个地发送请求,即在返回上一个响应后发送下一个请求。您可以使用ReactiveCocoa 使您的代码更优雅。或者使用我写的STNetTaskQueue的网络库,有一个STNetTaskChain可以处理一个接一个的请求。

        2. 并行发送请求(就是你现在正在做的),并使用 NSDictionary 跟踪请求和响应,在所有请求完成后,按原始顺序组合响应。

        希望这会有所帮助!

        【讨论】:

          猜你喜欢
          • 2021-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-16
          • 1970-01-01
          • 2021-10-27
          • 1970-01-01
          • 2011-08-28
          相关资源
          最近更新 更多