2016-02-26 67 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

这几乎是我要去的,是的。很高兴你根据我的提示找到了一个可行的解决方案。然而,请留意我对你标记为“正确”的答案的评论 - 尽管如此,我不确定那一个是否真的是你想要的。 –