详解为Angular.js内置$http服务添加拦截器的方法


Posted in Javascript onDecember 20, 2016

前言

在Angular框架中,创建团队为使用者进行了Ajax请求的封装,并通过$http服务暴露出相关的接口.Angular在其官方文档中指出, $http服务底层针对Web常见的安全攻击做出了相应的对策,也就是说使用$http服务封装的Ajax为使用者提供了更为安全的保障.作为一个框架,保证框架的可用性,适配性是很有必要的. Angular在设计,实现中也体现出来了这样的良好风格.我们通常在使用Ajax时,有时候希望我们能够在请求发起前或接收到请求后做一些相应的处理工作,比如:在请求发起前,在请求头中添加一下报文段.在请求返回时对一请求处理状态做一些管理,如统一处理404状态等等.Angular的$http服务在设计实现时充分考虑到了上述的情况.接下来,我们一起来学习和了解一下如何为$http服务添加拦截器,以及如何在我们自己实现的服务中实现类似的拦截器机制.

什么是拦截器?What are Interceptors?

Interceptor(拦截器)在服务端框架中属于一种比较常见的机制,如spring,Struts2等Java框架中拦截器属于基本配置项.拦截器提供了一种机制可以使开发者可以定义在一个action(动作)执行的前后执行的代码,这些代码可以是在一个action执行前阻止其执行的代码,也可以是修改目标动作某些行为的代码.(在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。在Spring框架中比较常见)

$http服务中的拦截器

查看API或是源码我们可以发现,Angular的实现中通过 httpProvider提供了一个名为interceptors的数组.这个数组接受拦截器服务注册,通过过程次的注册最终会形成拦截器链.这样每次在调用http服务的时候,angular都会通过我们定义的拦截点(切面)进行相应的Ajax动作修改.理论就不多说了,下面开始进入实战:

Angular中如何声明一个拦截器

// Interceptor declaration
module.factory('httpInterceptor', ['$log', function($log) {
  $log.debug('$log is here to show you that this is a regular factory with injection');

  return { 
      // do something
      };
}]);

如何将声明的拦截器注册到$http服务中

// Add the interceptor to $httpProvider.interceptors
module.config(['$httpProvider', function($httpProvider) { 
  $httpProvider.interceptors.push('httpInterceptor');
}]);

通过上面的简单两个步骤,我们基本就完成了http服务的拦截器编写与添加.但是上面的代码片段并不能实际使用,要想真正的实现拦截操作,我们还需要遵循http服务暴露出来的可以进行拦截的点进行相关的代码编写.

$httpProvider暴露了那些可以拦截的点?

  1. request : request方法可以实现拦截请求: 该方法会在 http发送请求到服务器之前执行,因此我们可以在该方法的视线中修改配置或做其他的操作。该方法接收请求配置对象(requestconfigurationobject)作为参数,然后必须返回配置对象或者promise。如果返回无效的配置对象或者promise则会被拒绝,导致http 调用失败。
  2. response : response方法可以实现拦截响应: 该方法会在 http接收到从服务器过来的响应之后执行,因此我们可以修改响应报文或做其他操作。该方法接收响应对象(responseobject)作为参数,然后必须返回响应对象或者promise。响应对象包括了请求配置(requestconfiguration),头(headers),状态(status)和从后台过来的数据(data)。如果返回无效的响应对象或者promise会被拒绝,导致http 调用失败。
  3. requestError : requestError方法可以实现拦截请求异常: 有时候一个请求发送失败或者被拦截器拒绝了。请求异常拦截器会俘获那些被上一个请求拦截器中断的请求。它可以用来恢复请求或者有时可以用来撤销请求之前所做的配置,比如说关闭进度条,激活按钮和输入框什么之类的。
  4. responseError : responseError方法可以实现拦截响应异常: 有时候我们后台调用失败了。也有可能它被一个请求拦截器拒绝了,或者被上一个响应拦截器中断了。在这种情况下,响应异常拦截器可以帮助我们恢复后台调用。

对于上面暴露出来的接口使用也是异常的简单的,我们可以像声明一个简单的服务一样声明一个$http服务的拦截器,并交由angular的注入机制去使用我们配置的拦截器.

// 如同声明一个Angular服务一样声明一个拦截器
module.factory('sessionInjector', ['authService', function (authService){
  return {
    request: function (config){
      if (!authService.isAnonymus) {
        config.headers['x-session-token'] = authService.token;
      }
      return config;
    }
  };
}]);

// 然后将我们声明的拦截器添加到$httpProvider的拦截器链中,之后的服务注入Angular会负责帮我们完善
module.config(['$httpProvider', function ($httpProvider){
  $httpProvider.interceptors.push('sessionInjector');
}]);

$http服务拦截器的异步支持

部分场景下,我们希望在拦截器中能够执行一些异步操作.然后依据不同的处理结果进行不同的拦截操作,AngularJS在设计的时候也很好的支持了这一特性.AngularJS允许我们在拦截的方法中,我们可以返回一个promise对象.如在http服务中,我们如果返回一个promise对象时,http服务将会延迟发起网络请求或是延迟响应请求结果.

module.factory('myInterceptor', ['$q', 'someAsyncService', function($q, someAsyncService) {
  var requestInterceptor = {
    request: function(config) {
      var deferred = $q.defer();
      someAsyncService.doAsyncOperation().then(function() {
        // Asynchronous operation succeeded, modify config accordingly
        ...
        deferred.resolve(config);
      }, function() {
        // Asynchronous operation failed, modify config accordingly
        ...
        deferred.resolve(config);
      });
      return deferred.promise;
    },
    response: function(response) {
          var deferred = $q.defer();
          someAsyncService.doAsyncOperation().then(function() {
            // Asynchronous operation succeeded, modify response accordingly
            ...
            deferred.resolve(response);
          }, function() {
            // Asynchronous operation failed, modify response accordingly
            ...
            deferred.resolve(response);
          });
          return deferred.promise;
        }
  };

  return requestInterceptor;
}]);

上面的例子中,在请求发起时,如果对应的deferred被拒绝,http请求则会失败(如果进行抓包分析的话,你会发现http请求并没有发起).在请求进行响应时,如果deferred被拒绝,则请求也会失败.(抓包分析,网络请求是有返回的).

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
javascript简易缓动插件(源码打包)
Feb 16 Javascript
jQuery ajax(复习)—Baidu ajax request分离版
Jan 24 Javascript
PHP中使用微秒计算脚本执行时间例子
Nov 19 Javascript
jquery读写cookie操作实例分析
Dec 24 Javascript
基于React.js实现原生js拖拽效果引发的思考
Mar 30 Javascript
jQuery遍历json的方法(推荐)
Jun 12 Javascript
Javascript中的对象和原型(二)
Aug 12 Javascript
基于JavaScript实现复选框的全选和取消全选
Feb 09 Javascript
微信公众号菜单配置微信小程序实例详解
Mar 31 Javascript
详解Vue.js Mixins 混入使用
Sep 15 Javascript
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
Dec 14 Javascript
如何在vue中使用kindeditor富文本编辑器
Dec 19 Vue.js
[Bootstrap-插件使用]Jcrop+fileinput组合实现头像上传功能实例代码
Dec 20 #Javascript
JS简单实现表格排序功能示例
Dec 20 #Javascript
深入了解JavaScript的逻辑运算符(与、或)
Dec 20 #Javascript
js定时器实例分享
Dec 20 #Javascript
BootStrap Table 获取同行不同列元素的方法
Dec 19 #Javascript
Jquery Easyui进度条组件Progress使用详解(8)
Mar 26 #Javascript
详解Jquery的事件操作和文档操作
Dec 19 #Javascript
You might like
php 修改zen-cart下单和付款流程以防止漏单
2010/03/08 PHP
Laravel监听数据库访问,打印SQL的例子
2019/10/24 PHP
Laravel 微信小程序后端实现用户登录的示例代码
2019/11/26 PHP
jquery实现心算练习代码
2010/12/06 Javascript
silverlight线程与基于事件驱动javascript引擎(实现轨迹回放功能)
2011/08/09 Javascript
JavaScript 中的日期和时间及表示标准介绍
2013/08/21 Javascript
javascript实现控制文字大中小显示
2015/04/28 Javascript
jQuery异步上传文件插件ajaxFileUpload详细介绍
2015/05/19 Javascript
纯javascript实现四方向文本无缝滚动效果
2015/06/16 Javascript
JS实现兼容各种浏览器的获取选择文本的方法【测试可用】
2016/06/21 Javascript
Vue.js系列之项目搭建(1)
2017/01/03 Javascript
JavaScript实现类似淘宝的购物车效果
2017/03/16 Javascript
老生常谈angularjs中的$state.go
2017/04/24 Javascript
vue 中自定义指令改变data中的值
2017/06/02 Javascript
vue template中slot-scope/scope的使用方法
2018/09/06 Javascript
JS实现点击按钮随机生成可拖动的不同颜色块示例
2019/01/30 Javascript
如何用JavaScript实现功能齐全的单链表详解
2019/02/11 Javascript
vue前端框架—Mint UI详解(更适用于移动端)
2019/04/30 Javascript
Node.js爬虫如何获取天气和每日问候详解
2019/08/26 Javascript
深入探索VueJS Scoped CSS 实现原理
2019/09/23 Javascript
uni-app如何实现增量更新功能
2020/01/03 Javascript
jquery实现简单自动轮播图效果
2020/07/29 jQuery
微信小程序对图片进行canvas压缩的方法示例详解
2020/11/12 Javascript
[42:52]Optic vs Serenity 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
Python实现动态图解析、合成与倒放
2018/01/18 Python
使用python编写udp协议的ping程序方法
2018/04/22 Python
详谈Python3 操作系统与路径 模块(os / os.path / pathlib)
2018/04/26 Python
Django页面数据的缓存与使用的具体方法
2019/04/23 Python
python单向循环链表原理与实现方法示例
2019/12/03 Python
浅谈keras的深度模型训练过程及结果记录方式
2020/01/24 Python
结合CSS3的布局新特征谈谈常见布局方法
2016/01/22 HTML / CSS
HTML5有哪些新特征
2015/12/01 HTML / CSS
北美Newegg打造的全球尖货海购平台:tt海购
2018/09/28 全球购物
荷兰网上药店:Drogisterij.net
2019/09/03 全球购物
家长会欢迎词
2015/01/23 职场文书
Java 在线考试云平台的实现
2021/11/23 Java/Android