我正在使用$http
拦截器捕获ajax提交后的所有事件。出于某种原因,我无法抛出requestError
。我已经设置了一个测试应用来尝试拨打requestError
,但到目前为止,我只能获得多个responseErrors
。
来自 angularjs docs:
requestError :当前一个拦截器抛出错误或通过拒绝解决时,会调用拦截器。
这是我的测试代码。
.factory('httpInterceptor',['$q',function(q){
var interceptor = {};
var uniqueId = function uniqueId() {
return new Date().getTime().toString(16) + '.' + (Math.round(Math.random() * 100000)).toString(16);
};
interceptor.request = function(config){
config.id = uniqueId();
console.log('request ',config.id,config);
return config;
};
interceptor.response = function(response){
console.log('response',response);
return response;
};
interceptor.requestError = function(config){
console.log('requestError ',config.id,config);
return q.reject(config);
};
interceptor.responseError = function(response){
console.log('responseError ',response.config.id,response);
return q.reject(response);
};
return interceptor;
}])
.config(['$httpProvider',function($httpProvider) {
$httpProvider.interceptors.push('httpInterceptor');
}])
.controller('MainCtrl',['$http',function($http){
var mainCtrl = this;
mainCtrl.method = null;
mainCtrl.url = null;
var testHttp = function testHttp() {
$http({method:mainCtrl.method,url:mainCtrl.url}).then(
(response)=>{console.log('ok',response);},
(response)=>{console.log('reject',response);}
);
};
//api
mainCtrl.testHttp = testHttp;
}])
我尝试了多种创建http错误的方法,每次只调用responseError
。我尝试过的事情:
400
和500
。sleep
,以便稍后请求在之前的请求之前响应错误。相同的资源,相同的服务器响应。404
错误。responseError -1
)。类似问题
关键的paragrapgh是:
关键是上述任何一种方法都可以返回 “普通”对象/原语或将用一个解决的承诺 适当的价值。在后一种情况下,下一个拦截器在 queue将等待,直到返回的promise被解决或拒绝。
但我认为我正在做它所规定的内容,即服务器随机sleep
,但没有运气。我从请求中得到reponseErrors
故障,即服务器响应后。
2)大约一年前提出了类似的问题:Angular and Jasmine: How to test requestError / rejection in HTTP interceptor?
不幸的是,它只提供interceptors
的解释。它没有回答我的问题。
我已在 Chrome 和 Firefox 中进行了测试。我希望你理解,我已经尽力找到解决方案,但我还没有找到解决方案。
答案 0 :(得分:2)
这是因为请求在任何时候都没有被拒绝。应该使用like that:
app.factory('interceptor1', ['$q', function ($q) {
return {
request: function (config) {
console.log('request', config);
if (config.url === 'restricted')
return $q.reject({ error: 'restricted', config: config });
}
};
}]);
app.factory('interceptor2', ['$q', function ($q) {
return {
requestError: function (rejection) {
console.log('requestError', rejection);
if (rejection.error === 'restricted')
return angular.extend(rejection.config, { url: 'allowed' });
return $q.reject(rejection);
}
};
}]);
app.config(['$httpProvider',function($httpProvider) {
$httpProvider.interceptors.push('interceptor1');
$httpProvider.interceptors.push('interceptor2');
}]);
请注意,拦截器应该在堆栈中工作(从transform*
请求中的$http
挂钩开始),因此请求不能在单个拦截器中被拒绝和恢复。
答案 1 :(得分:2)
我知道我来晚了,但是我遇到了同样的问题,但是我没有发现其他答案特别有用。因此,在花了几个小时研究AngularJS拦截器之后,我想分享我学到的东西。
拦截器不直观,并且有很多“陷阱”。我和线程作者陷入其中。这样的问题可以通过更好地了解幕后执行流程来解决。此帖子最具体的地方是帖子末尾的Gotchas#3和#6。
您知道,$ httpProvider具有一个名为“ interceptors”的属性,该属性以一个空数组开头,可以存储一个或多个 interceptors 。 拦截器是具有四个可选方法的对象: request , requestError , response 和 responseError 。该文档对这些方法几乎没有说什么,但确实引起误解和不完整。还不清楚何时调用这些命令以及调用顺序。
正如其他评论/答案中所述,拦截器方法最终都链接在一起,形成一个很大的承诺链。如果您不熟悉Promise,拦截器将毫无意义($ http服务也不会)。即使您了解了诺言,拦截器还是有点奇怪。
我将向您展示一个示例,而不是试图解释执行流程。假设我已经在$ httpProvider.interceptors数组中添加了以下三个拦截器。
当我通过$ http发出请求时,幕后发生的执行流程如下所示。请注意,绿色箭头表示该函数已解决,红色箭头表示该函数已被拒绝(如果抛出错误,它将自动发生)。箭头旁边的标签指示已解决或拒绝的值。
哇,那太复杂了!我不会逐步介绍它,但是我想指出一些可能会使程序员挠头的事情。
首先要注意的是,与流行的看法相反,将错误的配置对象传递给$ http()不会触发 requestError 函数-它不会触发任何拦截器方法。它将导致正常的旧错误并停止执行。
流程中没有横向移动-每个解决或拒绝都会将执行向下移动。如果成功处理程序之一(蓝色)中发生错误,则不调用同一拦截器中的错误处理程序(橙色);如果存在的话,则称为下一个下一级。这导致陷阱编号3 ...
如果您在第一个拦截器中定义了 requestError 方法,则它将永远不会被调用。除非我错误地阅读了angularjs库代码,否则在执行流程中似乎完全无法访问此类函数。这就是让我感到困惑的原因,而且似乎也可能是原始问题中的一部分。
如果最后一个拦截器的 request 或 requestError 方法拒绝,则不会发送该请求。只有解决了,Angular才会实际尝试发送请求。
如果请求发送失败或响应状态不是2XX,它将拒绝并触发第一个 responseError 。这意味着您的第一个 responseError 方法必须能够处理两种不同的输入:如果“发送”功能失败,则输入将是错误;但是如果响应为401,则输入将为响应对象。
一旦开始,就无法打破链条。这似乎也是原始问题中的一部分。当最后一个 requestError 拒绝时,它会跳过发送请求,但是会立即调用第一个 responseError 。直到链接完成,执行才会停止,即使某些操作在早期失败。
我认为此线程的作者很早以前就解决了他们的问题(没有双关语),但是我希望这可以帮助其他人。
答案 2 :(得分:0)
您提出了responseError,因为您的所有示例的响应都有错误。您可以通过尝试在请求中发送无效的json或不正确地格式化请求来获取请求错误。