2017-06-20 26 views
0

我有一个使用Alamofire进行URL请求的iOS应用程序。当他们之间的时间很少时,我有时会发现请求按错误顺序到达。这与我所了解的异步请求的性质有关。有什么方法可以保证请求的正确顺序吗?我一直认为你可以等待每个请求完成,因为你有一个完成处理程序,或者你可以在服务器端处理每个请求的时间戳,以便服务器可以放弃具有较低时间戳的请求。我不知道什么是最好的解决方案。如何保证异步请求中的正确顺序

我迄今为止代码:

Alamofire.request(
    defaults.string(forKey: "APIurl")! + path, 
    method: httpMethod, 
    parameters: parameters, 
    encoding: JSONEncoding.default, 
    headers: headers).responseJSON 
    { response in 

    // Check if the request was successful 
    var success = false 
    if (response.result.isSuccess) { 
     let statusCode = response.response!.statusCode 
     if (statusCode == 200) { 
      success = true 
     } else { 
      showAlert("COULD_NOT_COMPLETE_TASK_TITLE", message: "TRY_AGAIN_LATER") 
     } 
    } 

} 

我用滑块改变所以在我的情况下,请求的顺序是至关重要的0和100之间的值。比方说,我将滑块从50更改为60.使用异步请求时,它有时会先执行60次然后执行50.这是一个问题,因为它以这种方式发送到我的API并将最新值(在本例中为50)保存在数据库中尽管我的期望值是60.

+2

你不能保证异步请求的顺序,你必须做你的逻辑来处理后做什么的要求又回来了。 – WeiJay

+0

如果订单很重要,那么可以顺序发送请求或在完成所有请求后协调响应 – Paulw11

+1

确保订单完成的唯一方法是在第一个请求完成之前不要发出第二个请求(这是一个非常愚蠢的方法解决问题)。 Wei Jay是对的,你应该编写不依赖于响应进来的顺序的代码。尽管没有更多的上下文,但我们无法帮助你解决这个问题。但是,再一次,既然我们已经指出,你需要按照他们可能的顺序来处理它们,你也可以把它弄清楚。 – Rob

回答

0

如果线程是串行的,那么在您的情况下,它的顺序将始终与您输入的顺序相同。因此,在同一个串行线程上异步调用几个操作将强制操作保留该顺序。

你的情况的问题是你没有调用这些操作,Alamofire正在调用它们。顺序被保留,但是取决于何时收到和解析响应。这意味着你可能无法控制被调用的异步操作的顺序。

你有2周串行的方式回应:

  1. 你需要等待每个响应调用的下一个请求之前完成。如果你的回答是标准的(看起来都很相似),你只需要一些管理员来存储一系列请求,并且在上一个请求完成之前不会调用新的请求。这可能有点慢,因为没有理由(或者至少在你的情况下似乎是这样)不同时执行请求。

  2. 将响应序列化,以便按照与输入相同的顺序调用它们。这意味着您每当调用请求时,都会调用响应。但是,一旦收到回复,您将检查其他回复是否完成,并且只有在回复完成后才会触发此回复。这又意味着让一些经理序列化那里的回应。

所以对于第二个,你会需要这样的东西:

SerializedRequestManager.performRequest(request, myCallbackClosure) 

那么管理者将保存请求转换成要求包装的一些阵列,如:

let requestWrapper = RequestWrapper(request, myCallbackClosure, isCompleted: false) 
self.requestPool.append(requestWrapper) 
AF.performRequest(request, myInternalClosure) 

然后在反应(myInternalClosure),您需要设置正确的包装器,使其具有对true的响应,然后从阵列的起始处刷新响应。然后完成所有的反应必须从阵列中删除:

requestWrapper.responseData = data // Same wrapper that was just added into the array 
requestWrapper.responseError = error // Same wrapper that was just added into the array 
requestWrapper.isCompleted = true 
self.flushResponses() 

所以后来flushResponses

var newPool = [RequestWrapper]() // This is where all the pending items will stay 
var shouldFlushResponse = true // Will be set to false with first request that was not completed 
self.requestPool.forEach { wrapper in 
    if wrapper.isCompleted && shouldFlushResponse { 
     wrapper.callback(wrapper.responseData, wrapper.responseError) // perform response closure 
    } else { 
     shouldFlushResponse = false 
     newPool.append(wrapper) 
    } 
} 
self.requestPool = newPool 

但是你必须非常小心这里的多线程。数组requestPool上的所有操作应该在同一个线程上完成,但它可能是您想要的任何线程。

0

那么如果在你的情况下关键的请求的顺序,那么你应该去NSOperationQueue,这是唯一的方法来确保您的请求的顺序。

按照this教程有边界的想法