详解Angular.js中$http拦截器的介绍及使用

发布时间 - 2026-01-11 02:10:28    点击率:

前言

$http service在Angular中用于简化与后台的交互过程,其本质上使用XMLHttpRequest或JSONP进行与后台的数据交互。在与后台的交互过程中,可能会对每条请求发送到Server之前进行预处理(如加入token),或者是在Server返回数据到达客户端还未被处理之前进行预处理(如将非JSON格式数据进行转换);当然还有可能对在请求和响应过程过发生的问题进行捕获处理。所有这些需求在开发中都非常常见,所以Angular为我们提供了$http拦截器,用来实现上述需求。

什么是拦截器

顾名思义,拦截器就是在目标达到目的地之前对其进行处理以便处理结果更加符合我们的预期。Angular的$http拦截器是通过$httpProvider.interceptors数组定义的一组拦截器,每个拦截器都是实现了某些特定方法的Factory:

实现拦截器

http拦截器一般通过定义factory的方式实现:

myApp.factory('MyInterceptor', function($q) {
 return {
 // 可选,拦截成功的请求
 request: function(config) {
  // 进行预处理
  // ...
  return config || $q.when(config);
 },

 // 可选,拦截失败的请求
 requestError: function(rejection) {
  // 对失败的请求进行处理
  // ...
  if (canRecover(rejection)) {
  return responseOrNewPromise
  }
  return $q.reject(rejection);
 },



 // 可选,拦截成功的响应
 response: function(response) {
  // 进行预处理
  // ....
  return response || $q.when(reponse);
 },

 // 可选,拦截失败的响应
 responseError: function(rejection) {
  // 对失败的响应进行处理
  // ...
  if (canRecover(rejection)) {
  return responseOrNewPromise
  }
  return $q.reject(rejection);
 }
 };
});

随后,我们需要将实现的拦截器加入到$httpProvider.interceptors数组中,此操作一般在config方法中进行:

myApp.config(function($httpProvider) {
 $httpProvider.interceptors.push(MyInterceptor);
});

当然,我们也可以通过匿名factroy的方式实现:

$httpProvider.interceptors.push(function($q) {
 return {
 request: function(config) {
  // bala
 },

 response: function(response) {
  // bala
 },

 // bala
 };
});

可以看到,每个拦截器都可以实现4个可选的处理函数,分别对应请求(成功/失败)和响应(成功/失败)的拦截:

1、request:此函数在$http向Server发送请求之前被调用,在此函数中可以对成功的http请求进行处理,其包含一个http config对象作为参数,这里对config对象具有完全的处理权限,甚至可以重新构造,然后直接返回此对象或返回包含此对象的promise即可。如果返回有误,会造成$http请求失败。如开发中经常需要在请求头中加入token以便验证身份,我们可以作如下处理:

request: function(config) {
 config.headers = config.headers || {};
 if ($window.sessionStorage.token) {
  config.headers['X-Access-Token'] = $window.sessionStorage.token;
 }
 return config || $q.when(config);
}

2、requestError:此方法会在前一个拦截器抛出异常或进行了reject操作时被调用,在这里可以进行恢复请求的操作,或者进行一些对于请求时发起动作的处理(如取消loading等);

3、response:此函数在$http从Server接收到响应时被调用,在此函数中可以对成功的http响应进行处理,这里具有对响应的完全处理权限,甚至可以重新构造,然后直接返回响应或返回包含响应的promise即可。如果返回有误,会造成$http接收响应失败;

4、responseError:此方法会在前一个拦截器抛出异常或进行了reject操作时被调用,在这里可以进行恢复响应的操作,进行一些针对错误的处理。

使用用例

为演示Angular $http拦截器的使用方法,下面通过几个常用的用例来说明:

利用request拦截器模拟实现Angular的XSRF(即CSRF)防御

CSRF,即“跨站请求伪造”,不过不知道为什么Angular将其称为XSRF。当处理与后台交互时,Angular的$http会尝试从客户端cookie中读取一个token,其默认的key为XSRF-TOKEN,并构造一个名为X-XSRF-TOKEN的http头部,与http请求一起发送到后台。Server端就可以根据此token识别出请求来源于同域,当然跨域的请求$http不会加入X-XSRF-TOKEN头部。那我们可以利用request拦截器通过如下方式在同域请求头部中加入此头部以达到模拟Angular的XSRF(即CSRF)防御机制的实现效果:

/**
* 正式开发中Angular会主动进行XSRF防御(只要cookie中存在key为`XSRF-TOKEN`的token),
* 一般不需要手动进行,除非cookie中不存在key为`XSRF-TOKEN`的token,这里只是模拟实现
*/
request: function(config) {
 if(config.url.indexOf('SAME_DOMAIN_API_URL') > -1) {
 config.headers['X-XSRF-TOKEN'] = $cookies.get('XSRF-TOKEN');
 }
 return config;
}

如果初始http请求头部类似于:

"headers": {
 "Accept": "application/json, text/plain, */*"
}

那么经过上述的拦截器后,其http请求头部就变成了:

"headers": {
 "Accept": "application/json, text/plain, */*",
 "X-XSRF-TOKEN": X-XSRF-TOKEN-VALUE
}

利用response拦截器模拟实现Angular JSON易损性(JSON vulnerability)防御

Angular在$http请求安全性方面不仅为我们设计了XSRF(CSRF)防御,而且针对请求JSON数据的Url可能通过类似于<script>标签加载的方式被恶意网站获取到我们的JSON数据的情况,设计了Angular JSON易损性(JSON vulnerability)防御,即Server端返回的JSON数据头部可以添加")]}',\n"字符串,得到包含此前缀的响应数据后,Angular会将此前缀删去,将响应还原成正式的JSON数据。此时我们就可以通过response拦截器模拟此过程:

response: function(response) {
 var data = examineJSONResponse(response); // 假设存在这样一个方法
 if(!data) {
  response = validateJSONResponse(response); // 假设存在这样一个方法
 }
 return response || $q.when(reponse);
}

利用request拦截器和response拦截器计算http请求耗时

这个需求可能在开发中并不常用,这里只是作为同时使用request拦截器和response拦截器的例子,我们可以在request拦截器和response拦截器中分别计时,然后求得其差值即可:

myApp.factory('timestampMarker', [function() {
 return {
  request: function(config) {
   config.requestTimestamp = new Date().getTime();
   return config;
  },
  response: function(response) {
   response.config.responseTimestamp = new Date().getTime();
   return response;
  }
 };
}]);
myApp.config(['$httpProvider', function($httpProvider) {
 $httpProvider.interceptors.push('timestampMarker');
}]);

这样我们在每次请求后台时,就能够计算出相应请求的耗时了,如:

$http.get('https://api.github.com/users/liuwenzhuang/repos').then(function(response) {
 var time = response.config.responseTimestamp - response.config.requestTimestamp;
 console.log('The request took ' + (time / 1000) + ' seconds.');
});

总结

$http作为Angular中的核心service,其功能非常强大便捷,今天描述了其子功能http拦截器的概念和描述方式,有理解不正确的地方,请大家留言告知。


# angularjs  # http拦截器  # angular  # angular2  # 浅析AngularJs HTTP响应拦截器  # 快速学习AngularJs HTTP响应拦截器  # 详解为Angular.js内置$http服务添加拦截器的方法  # 拦截器  # 可选  # 在这里  # 在此  # 我们可以  # 发送到  # 在前  # 类似于  # 以对  # 抛出  # 进行了  # 就可以  # 都是  # 客户端  # 法会  # 几个  # 是在  # 不需要  # 请大家  # 将其 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 高性价比服务器租赁——企业级配置与24小时运维服务  5种Android数据存储方式汇总  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  php json中文编码为null的解决办法  Laravel怎么实现微信登录_Laravel Socialite第三方登录集成  Android实现代码画虚线边框背景效果  实现点击下箭头变上箭头来回切换的两种方法【推荐】  Android自定义listview布局实现上拉加载下拉刷新功能  Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】  使用豆包 AI 辅助进行简单网页 HTML 结构设计  Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知  如何用PHP工具快速搭建高效网站?  晋江文学城电脑版官网 晋江文学城网页版直接进入  简单实现Android文件上传  Laravel如何实现多对多模型关联?(Eloquent教程)  如何用美橙互联一键搭建多站合一网站?  Laravel中间件如何使用_Laravel自定义中间件实现权限控制  详解阿里云nginx服务器多站点的配置  智能起名网站制作软件有哪些,制作logo的软件?  简历在线制作网站免费版,如何创建个人简历?  Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】  Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能  Laravel如何实现模型的全局作用域?(Global Scope示例)  Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】  郑州企业网站制作公司,郑州招聘网站有哪些?  Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  什么是JavaScript解构赋值_解构赋值有哪些实用技巧  如何在宝塔面板创建新站点?  如何在景安云服务器上绑定域名并配置虚拟主机?  如何在万网利用已有域名快速建站?  UC浏览器如何设置启动页 UC浏览器启动页设置方法  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  Laravel如何优化应用性能?(缓存和优化命令)  PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)  Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践  Laravel如何使用Vite进行前端资源打包?(配置示例)  Linux系统运维自动化项目教程_Ansible批量管理实战  Laravel的.env文件有什么用_Laravel环境变量配置与管理详解  Java垃圾回收器的方法和原理总结  高防服务器:AI智能防御DDoS攻击与数据安全保障  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  Laravel Asset编译怎么配置_Laravel Vite前端构建工具使用  使用Dockerfile构建java web环境  Windows Hello人脸识别突然无法使用  Laravel如何使用Service Container和依赖注入?(代码示例)  Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出  Laravel模型关联查询教程_Laravel Eloquent一对多关联写法  韩国服务器如何优化跨境访问实现高效连接?  Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程  Laravel如何使用Gate和Policy进行授权?(权限控制)