2016-02-26 101 views
1

我試圖添加一個彈出式重試選項,如下所示,以便用戶可以在HTTP調用期間失去連接時單擊它。AngularJS攔截器不成功返回

angular.module('app.services', []) 

.factory('httpResponseErrorInterceptor', ['$injector', '$q', function($injector, $q) { 
    return { 
     'responseError': function(response) { 
      var $ionicPopup = $injector.get('$ionicPopup'); 
      if (response.status === 0) { 
        var confirmPopup = $ionicPopup.confirm({ 
         title: 'No Connectivity!', 
         template: 'Internet not available' 
        }); 

        confirmPopup.then(function(res) { 
         if(res) { 
          var $http = $injector.get('$http'); 
          return $http(response.config); 
         } else { 
          return $q.reject(response); 
         } 
        }); 
      } 
     } 
    }; 
}]) 

它正在接收來自http調用的響應,但沒有將響應返回給調用點。以同樣的方式我嘗試下面的代碼,

.factory('httpResponseErrorInterceptor', ['$injector', '$q', function($injector, $q) { 
    return { 
    'responseError': function(response) { 
     if (response.status === 0) { 
     var $http = $injector.get('$http'); 
     return $http(response.config); 
     } 
     return $q.reject(response); 
    } 
    }; 
}]) 

但是,當我們得到的連接回這個人是正確的返回響應到調用點。我不確定第一個代碼中哪裏出錯。

任何幫助/想法,將不勝感激。

回答

2

您應該返回confirmPopup.then()調用。

這樣做:鏈接的

return confirmPopup.then(function(res) { 
    if(res) { 
     var $http = $injector.get('$http'); 
     return $http(response.config); 
    } else { 
     return $q.reject(response); 
    } 
}); 

例子:

var promise = confirmPopup.then(function(res) { 
    if(res) { 
     var $http = $injector.get('$http'); 
     return $http(response.config); 
    } else { 
     return $q.reject(response); 
    } 
}); 


promise.then(function(success){ 
    //HTTP SUCCESS 
}, function(error){ 
    //HTTP ERROR OR REJECT RESPONSE 
}); 
+0

您好,感謝您的解決方案,它的工作原理。只是澄清一下,是不是必須使用'defer'和'resolve'? – Stranger

+1

沒有必要。此退貨僅用於鏈接承諾。一個很好的參考是https://docs.angularjs.org/api/ng/service/$q - 「鏈接承諾」 –

+0

你確定這是可行的嗎?對我來說,它看起來像你返回的確認彈出承諾,而不是http承諾,這將導致傳遞給你的外部回調(調用者之一)的錯誤參數。 它應該通過「res」值而不是「response.config」 –

1
confirmPopup.then(function(res) { 
         if(res) { 
          var $http = $injector.get('$http'); 
          return $http(response.config); 
         } else { 
          return $q.reject(response); 
         } 
        }); 

這裏是問題所在。您在confirmPopup的異步回調中返回東西($ http/$ q)。 confirmPopup是異步的,您可以通過「.then」定義回調。 無論你回到那裏,都不會達到你的呼叫點。它是回調的返回值。這可能不會在任何地方降落(取決於confirmPopup的實現,但我懷疑它希望你任何回報有)

你將不得不使用自己的承諾,並將其返回同步在回調結束

2

基於Patrick Kelleter的回答,我編造了這個工作的解決方案,

.factory('httpResponseErrorInterceptor', ['$injector', '$q', function($injector, $q) { 
    return { 
     'responseError': function(response) { 
      var $ionicPopup = $injector.get('$ionicPopup'); 
      var $ionicLoading = $injector.get('$ionicLoading'); 
      $ionicLoading.hide(); 

      if (response.status === 0) { 
       var userInputDefer = $q.defer();     
       var confirmPopup = $ionicPopup.confirm({ 
        title: 'No Connectivity!', 
        template: 'Internet not available', 
        okText: 'Retry' 
       }); 

       confirmPopup.then(function(res) { 
        if(res) { 
         var $http = $injector.get('$http'); 
         userInputDefer.resolve($http(response.config)); 
        } else { 
         userInputDefer.reject($q.reject(response)); 
        } 
       }); 

       return userInputDefer.promise; 
      } 
     } 
    }; 
}]); 

編輯:

只是爲了某人將來參考,使用上述HTTP攔截器,你必須包括工廠的配置如下,

.config(['$httpProvider',function($httpProvider) { 
    $httpProvider.interceptors.push('httpResponseErrorInterceptor'); 
}]); 
+0

這幾乎是我要去的,是的。很高興你根據我的提示找到了一個可行的解決方案。然而,請留意我對你標記爲「正確」的答案的評論 - 儘管如此,我不確定那一個是否真的是你想要的。 –