2015-05-18 31 views
1

我試圖使用HTTP-Interceptor處理$ http請求超時並確保請求函數實際上得到了它後面的響應。 Retry request with $http interceptor適合我但是,它立即重試。我真正感興趣的是等待5秒鐘,然後重試。此外,我還希望用戶能夠立即觸發重試。

我正在試圖做的是一樣的東西下面:

joinApp.factory('httpResponseErrorInterceptor',function($q, $injector, $interval) { 
    return { 
    'responseError': function(response) { 
     if (response.status === 0) { 
     setTimeToRetry(5); //sets retry timeout to 5 seconds, and starts an interval to reduce the count every second 
     // should retry 
     $interval(function(response) { 
      if(getTimeToRetry() <= 0) { //when retry timeout gets to 0, then retry - this also allows for a method that sets the retry timeout to 0 earlier so that a user can make an immediate retry 
      var $http = $injector.get('$http'); 
      return $http(response.config); 
      } 
     },1000) 

     } 
     // give up 
     return $q.reject(response); 
    } 
    }; 
}); 

joinApp.config(function($httpProvider) { 
    $httpProvider.interceptors.push('httpResponseErrorInterceptor'); 
}); 

(正如你看到的,我已經非常寬鬆,從該鏈接的答案複製的基礎代碼)

但什麼我發現,那麼當$http請求被重試時,它會成功完成HTTP請求,但尋找原始promise響應的代碼實際上並沒有得到它的結果。 我在猜測這是因爲$interval的存在實際上是移動了請求所在線程之外的響應,所以響應不會發送給同一個請求者,但這是一個猜測。

我也試過的是將$interval承諾與$http承諾掛鉤。像

var retryIntervalPromise = $interval(function(response) { 
    if(getTimeToRetry() <= 0) { //when retry timeout gets to 0, then retry 
    var $http = $injector.get('$http'); 
    return $http(response.config); 
    } 
},1000) 
.then(function() { 
    var $http = $injector.get('$http'); 
      return $http(response.config); 
      }); 
return retryIntervalPromise 

的東西,但我被告知,可以與$interval承諾要做的唯一一件事就是取消它,這似乎並沒有反正工作。

有沒有人有這樣的想法? 或者意圖是否有效,我剛剛做了一些可怕的錯誤? 謝謝!

+0

您可以與我們分享提交請求的代碼嗎?我的想法是,既然你做了重試,原來的承諾不再有效,所以你將不得不更新你等待的承諾,重試。 – kwangsa

+0

如果您只需要延遲,您爲什麼使用'$ interval'而不是'$ timeout'? –

+0

我正在使用'$ interval',以便我可以 - 通過用戶交互 - 將重試時間設置爲0,並因此強制立即重試。 –

回答

2

您可以從responseError函數返回一個「延遲」的承諾,將$ http承諾鏈接到該函數以再次嘗試。這是一個簡單的例子具有固定超時:

  responseError: function(response) { 
       if (response.status === 0) { 
        var $http = $injector.get('$http'); 

        var deferred = $q.defer(); 

        $timeout(function() { 
         deferred.resolve(true); 
        }, 5000); 

        return deferred.promise.then(function() { 
         return $http(response.config); 
        }); 
       } 
       return $q.reject(response); 
      } 

如果你需要一個可變延遲,您可以將其存儲在一個工廠或其他服務中的變量,並讓用戶界面改變它存在的其餘部分。下一次超時會觸發,它將從單例中讀取間隔的新值,並在再次觸發請求之前等待。

+0

這是延遲承諾解決方案的好辦法。正是我在找什麼。 – Alex