前言

$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拦截器的概念和描述方式,有理解不正确的地方,请大家留言告知。

详解Angular.js中$http拦截器的介绍及使用的更多相关文章

  1. Angular.js项目中使用gulp实现自动化构建以及压缩打包详解

    基于流的前端自动化构建工具,利用gulp可以提高前端开发效率,特别是在前后端分离的项目中。下面这篇文章主要给大家介绍了关于在Angular.js项目中使用gulp实现自动化构建以及压缩打包的相关资料,需要的朋友可以参考下。

  2. 使用Angular.js开发的注意事项

    这篇文章主要记录了一些在学习和使用angular.js踩到的坑和需要注意的点,方便以后自己查阅,也给同样遇到这些问题的朋友们一些帮助,有需要的朋友们下面来一起看看吧。

  3. 利用Angular+Angular-Ui实现分页(代码加简单)

    这篇文章主要介绍了利用Angular+Angular-Ui实现分页,利用Angular+Angular-Ui实现的分页分页代码更加简单,更加容易懂哦,相信本文的内容对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。

  4. 利用Angular.js编写公共提示模块的方法教程

    最近工作中会经常遇到一些公用提示,使用框架自带很多时候不方便所以便自己编写了一个公共提示模块,下面这篇文章主要介绍了利用Angular.js编写公共提示模块的方法教程,需要的朋友可以参考借鉴,下面来一起看看吧。

  5. Angular.js中定时器循环的3种方法总结

    这篇文章主要给大家总结了angular.js中定时器循环的3种方法,分别是利用$interlval实现、$timeout的递归调用来实现以及$timeout借助arguments.callee来实现,每种方法都给出了详细的示例艾玛供大家学习参考,需要的朋友们下面跟着小编一起来学习学习吧。

  6. 如何在Angular.JS中接收并下载PDF

    最近这两天公司正在做一个PDF协议下载的功能,目前的解决方案可以分为完全前端生成和后端生成两种方式。前端生成PDF有jsPDF 和pdfmake 两种方式,下面这篇文章就给大家分享下如何在Angular.JS中接收并下载PDF的方法,有需要的朋友们可以参考借鉴,下面来一起看看吧。

  7. AngularJs表单验证实例代码解析

    这篇文章主要介绍了AngularJs表单验证实例代码解析,非常不错,具有参考借鉴价值,需要的朋友可以参考下

  8. Angular.JS去掉访问路径URL中的#号详解

    最近天天都在用AngularJS,各类文档也都看过好几遍,但总是些编程上的事找不到优雅的解决办法。今天终于把AngularJS的项目访问路径URL里的#号去掉了,这个问题不见得有多难,关键是花多长时间去理解AngularJS框架本身,下面来看看详细介绍,需要的朋友可以参考下。

  9. Angular.js中控制器之间的传值详解

    angular中每个controller(控制器)都会有自己的$scope,通过为这个对象添加属性赋值,就可以将数据传递给模板进行渲染,每个$scope只会在自己控制器内起作用,而有时候需要用到其他控制器中的数据就要考虑到控制器之间参数的传递了,下面来看看详细的介绍。

  10. Angular.JS内置服务$http对数据库的增删改使用教程

    我们可以使用内置的$http服务直接同外部进行通信。$http服务只是简单的封装了浏览器原生的XMLHttpRequest对象,下面这篇文章主要给大家介绍了关于Angular.JS内置服务$http对数据库的增删改等操作的相关资料,需要的朋友可以参考下。

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部