AngularJS拦截器未成功返回

时间:2016-02-26 12:08:18

标签: angularjs ionic-framework

我正在尝试添加带有重试选项的弹出窗口,如下所示,以便用户在HTTP调用期间丢失连接时可以单击它。

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);
    }
  };
}])

但是当我们恢复连接时,这一个正确地将响应返回到调用点。我不确定第一个代码中我哪里出错了。

任何帮助/想法都将不胜感激。

3 个答案:

答案 0 :(得分: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
});

答案 1 :(得分: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中包含工厂,如下所示,

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

答案 2 :(得分: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的实现,但我怀疑它希望你返回任何东西)

您必须使用自己的承诺,并在回调结束时同步