2017-06-20 193 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教程有邊界的想法