浅析AngularJs HTTP响应拦截器


Posted in Javascript onDecember 28, 2015

为何要用拦截器?

任何时候,如果我们想要为请求添加全局功能,例如身份认证、错误处理等,在请求发送给服务器之前或服务器返回时对其进行拦截,是比较好的实现手段。

 angularJs通过拦截器提供了一个从全局层面进行处理的途径.

 拦截器允许你:

通过实现 request 方法拦截请求: 该方法会在 $http 发送请求道后台之前执行,因此你可以修改配置或做其他的操作。该方法接收请求配置对象(request configuration object)作为参数,然后必须返回配置对象或者 promise 。如果返回无效的配置对象或者 promise 则会被拒绝,导致 $http 调用失败。

通过实现 response 方法拦截响应: 该方法会在 $http 接收到从后台过来的响应之后执行,因此你可以修改响应或做其他操作。该方法接收响应对象(response object)作为参数,然后必须返回响应对象或者 promise。响应对象包括了请求配置(request configuration),头(headers),状态(status)和从后台过来的数据(data)。如果返回无效的响应对象或者 promise 会被拒绝,导致$http 调用失败。

通过实现 requestError 方法拦截请求异常: 有时候一个请求发送失败或者被拦截器拒绝了。请求异常拦截器会俘获那些被上一个请求拦截器中断的请求。它可以用来恢复请求或者有时可以用来撤销请求之前所做的配置,比如说关闭进度条,激活按钮和输入框什么之类的。

通过实现 responseError 方法拦截响应异常: 有时候我们后台调用失败了。也有可能它被一个请求拦截器拒绝了,或者被上一个响应拦截器中断了。在这种情况下,响应异常拦截器可以帮助我们恢复后台调用。

 拦截器的核心是服务工厂,通过向$httpprovider.interceptors数组中添加服务工厂。在$httpProvider中进行注册。

 angularJs提供四种拦截器,其中两种成功拦截器(request、response),两种失败拦截器(requestError、responseError)。

  在服务中添加一种或多种拦截器:

angular.module("myApp", []) 
  .factory('httpInterceptor', [ '$q', '$injector',function($q, $injector) { 
    var httpInterceptor = { 
      'responseError' : function(response) { 
        ...... 
        return $q.reject(response); 
      }, 
      'response' : function(response) { 
        ...... 
        return response; 
      }, 
      'request' : function(config) { 
        ...... 
        return config; 
      }, 
      'requestError' : function(config){ 
        ...... 
        return $q.reject(config); 
      } 
    } 
  return httpInterceptor; 
}

然后使用$httpProvider在.config()函数中注册拦截器

angular.module("myApp", []) 
.config([ '$httpProvider', function($httpProvider) { 
  $httpProvider.interceptors.push('httpInterceptor'); 
} ]);

  实际的例子:(对401、404的拦截)

routerApp.config([ '$httpProvider', function($httpProvider) { 
    $httpProvider.interceptors.push('httpInterceptor'); 
  } ]); 
  routerApp.factory('httpInterceptor', [ '$q', '$injector',function($q, $injector) { 
    var httpInterceptor = { 
      'responseError' : function(response) { 
        if (response.status == 401) { 
          var rootScope = $injector.get('$rootScope'); 
          var state = $injector.get('$rootScope').$state.current.name; 
          rootScope.stateBeforLogin = state; 
          rootScope.$state.go("login"); 
          return $q.reject(response); 
        } else if (response.status === 404) { 
          alert("404!"); 
          return $q.reject(response); 
        } 
      }, 
      'response' : function(response) { 
        return response; 
      } 
    } 
    return httpInterceptor; 
  }  
]);

Session 注入(请求拦截器)

这里有两种方式来实现服务端的认证。第一种是传统的 Cookie-Based 验证。通过服务端的 cookies 来对每个请求的用户进行认证。另一种方式是 Token-Based 验证。当用户登录时,他会从后台拿到一个 sessionToken。sessionToken 在服务端标识了每个用户,并且会包含在发送到服务端的每个请求中。

下面的 sessionInjector 为每个被俘获的请求添加了 x-session-token 头 (如果当前用户已登录):

<!-- lang: js -->
module.factory('sessionInjector', ['SessionService', function(SessionService) {
  var sessionInjector = {
    request: function(config) {
      if (!SessionService.isAnonymus) {
        config.headers['x-session-token'] = SessionService.token;
      }
      return config;
    }
  };
  return sessionInjector;
}]);
module.config(['$httpProvider', function($httpProvider) {
  $httpProvider.interceptors.push('sessionInjector');
}]);

然后创建一个请求:

<!-- lang: js -->
$http.get('https://api.github.com/users/naorye/repos');

被 sessionInjector 拦截之前的配置对象是这样的:

<!-- lang: js -->
{
  "transformRequest": [
    null
  ],
  "transformResponse": [
    null
  ],
  "method": "GET",
  "url": "https://api.github.com/users/naorye/repos",
  "headers": {
    "Accept": "application/json, text/plain, */*"
  }
}

被 sessionInjector 拦截之后的配置对象是这样的:

<!-- lang: js -->
{
  "transformRequest": [
    null
  ],
  "transformResponse": [
    null
  ],
  "method": "GET",
  "url": "https://api.github.com/users/naorye/repos",
  "headers": {
    "Accept": "application/json, text/plain, */*",
    "x-session-token": 415954427904
  }
}

以上内容给大家介绍了AngularJs HTTP响应拦截器的相关知识,希望本文分享能够给大家带来帮助。

Javascript 相关文章推荐
javascript 树控件 比较好用
Jun 11 Javascript
利用JQuery+EasyDrag 实现弹出可拖动的Div,同时向Div传值,然后返回Div选中的值
Oct 24 Javascript
基于jquery的合并table相同单元格的插件(精简版)
Apr 05 Javascript
jQuery学习笔记之 Ajax操作篇(二) - 数据传递
Jun 23 Javascript
javascript实现拖动元素交换位置
Nov 29 Javascript
jQuery遍历DOM的父级元素、子级元素和同级元素的方法总结
Jul 07 Javascript
JavaScript使用forEach()与jQuery使用each遍历数组时return false 的区别
Aug 26 Javascript
JavaScript使用math.js进行精确计算操作示例
Jun 19 Javascript
JavaScript实现图片懒加载的方法分析
Jul 05 Javascript
微信小程序使用 vant Dialog组件的正确方式
Feb 21 Javascript
Vue动态加载图片在跨域时无法显示的问题及解决方法
Mar 10 Javascript
vue中element 的upload组件发送请求给后端操作
Sep 07 Javascript
Bootstrap实现默认导航栏效果
Sep 21 #Javascript
Angularjs注入拦截器实现Loading效果
Dec 28 #Javascript
AngularJS进行性能调优的7个建议
Dec 28 #Javascript
浅析AngularJS Filter用法
Dec 28 #Javascript
jquery实现倒计时功能
Dec 28 #Javascript
基于jquery实现瀑布流布局
Jun 28 #Javascript
详解AngularJS Filter(过滤器)用法
Dec 28 #Javascript
You might like
php公用函数列表[正则]
2007/02/22 PHP
需要发散思维学习PHP
2009/06/29 PHP
PHP 5.3 下载时 VC9、VC6、Thread Safe、Non Thread Safe的区别分析
2011/03/28 PHP
php使用qr生成二维码的示例分享
2014/01/20 PHP
解决安装WampServer时提示缺少msvcr110.dll文件的问题
2017/07/09 PHP
用js实现多域名不同文件的调用方法
2007/01/12 Javascript
javascript调试说明
2010/06/07 Javascript
JS中的异常处理方法分享
2013/12/22 Javascript
js 事件截取enter按键页面提交事件示例代码
2014/03/04 Javascript
浅析js预加载/延迟加载
2014/09/25 Javascript
轻松创建nodejs服务器(5):事件处理程序
2014/12/18 NodeJs
详解JavaScript中jQuery和Ajax以及JSONP的联合使用
2015/08/13 Javascript
用director.js实现前端路由使用实例
2017/01/27 Javascript
使用openSpeDiv方法实现Ecshop登录弹窗框效果
2017/03/13 Javascript
干货!教大家如何选择Vue和React
2017/03/13 Javascript
JavaScript ES6中const、let与var的对比详解
2017/06/18 Javascript
详解Eslint 配置及规则说明
2018/09/10 Javascript
JavaScript时间日期操作实例小结【5个示例】
2018/12/22 Javascript
vue中axios请求的封装实例代码
2019/03/23 Javascript
详解ES6 export default 和 import语句中的解构赋值
2019/05/28 Javascript
微信小程序实现订单倒计时
2020/11/01 Javascript
解决layui富文本编辑器图片上传无法回显的问题
2019/09/18 Javascript
JavaScript enum枚举类型定义及使用方法
2020/05/15 Javascript
利用React高阶组件实现一个面包屑导航的示例
2020/08/23 Javascript
Python 字符串定义
2009/09/25 Python
python实现大文本文件分割
2019/07/22 Python
详解Python 字符串相似性的几种度量方法
2019/08/29 Python
Python3使用xml.dom.minidom和xml.etree模块儿解析xml文件封装函数的方法
2019/09/23 Python
通过实例简单了解Python中yield的作用
2019/12/11 Python
python数据库操作mysql:pymysql、sqlalchemy常见用法详解
2020/03/30 Python
Python爬虫之Selenium库的使用方法
2021/01/03 Python
CSS3 3D旋转rotate效果实例介绍
2016/05/03 HTML / CSS
大学新生军训个人的自我评价
2013/10/03 职场文书
劳资员岗位职责
2013/11/11 职场文书
Python办公自动化解决world文件批量转换
2021/09/15 Python
Redis特殊数据类型bitmap位图
2022/06/01 Redis