(转)Angular中的拦截器Interceptor
原文:Interceptors in AngularJS and Useful Examples
$httpAngularJS 的 $http
服务允许我们通过发送 HTTP 请求方式与后台进行通信。在某些情况下,我们希望可以俘获所有的请求,并且在将其发送到服务端之前进行操作。还有一些情况是,我们希望俘获响应,并且在完成完成调用之前处理它。一个很好例子就是处理全局 http 异常。拦截器(Interceptors)应运而生。本文将介绍 AngularJS 的拦截器,并且给几个有用的例子。
什么是拦截器?
$httpProvider
中有一个 interceptors
数组,而所谓拦截器只是一个简单的注册到了该数组中的常规服务工厂。下面的例子告诉你怎么创建一个拦截器:
module.factory( 'myInterceptor' , [ '$log' , function ($log) { $log.debug( '$log is here to show you that this is a regular factory with injection' ); var myInterceptor = { .... .... .... }; return myInterceptor; }]); |
然后通过它的名字添加到 $httpProvider.interceptors
数组:
module.config([ '$httpProvider' , function ($httpProvider) { $httpProvider.interceptors.push( 'myInterceptor' ); }]); |
拦截器允许你:
通过实现
request
方法拦截请求: 该方法会在$http
发送请求道后台之前执行,因此你可以修改配置或做其他的操作。该方法接收请求配置对象(request configuration object)作为参数,然后必须返回配置对象或者promise
。如果返回无效的配置对象或者 promise 则会被拒绝,导致$http
调用失败。通过实现
response
方法拦截响应: 该方法会在$http
接收到从后台过来的响应之后执行,因此你可以修改响应或做其他操作。该方法接收响应对象(response object)作为参数,然后必须返回响应对象或者promise
。响应对象包括了请求配置(request configuration),头(headers),状态(status)和从后台过来的数据(data)。如果返回无效的响应对象或者 promise 会被拒绝,导致$http
调用失败。通过实现
requestError
方法拦截请求异常: 有时候一个请求发送失败或者被拦截器拒绝了。请求异常拦截器会俘获那些被上一个请求拦截器中断的请求。它可以用来恢复请求或者有时可以用来撤销请求之前所做的配置,比如说关闭进度条,激活按钮和输入框什么之类的。通过实现
responseError
方法拦截响应异常: 有时候我们后台调用失败了。也有可能它被一个请求拦截器拒绝了,或者被上一个响应拦截器中断了。在这种情况下,响应异常拦截器可以帮助我们恢复后台调用。异步操作
有时候需要在拦截器中做一些异步操作。幸运的是, AngularJS 允许我们返回一个 promise
延后处理。它将会在请求拦截器中延迟发送请求或者在响应拦截器中推迟响应。
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; } }; return requestInterceptor; }]); |
这个例子中,请求拦截器使用了一个异步操作,根据结果来更新配置。然后它用更新后的配置继续执行操作。如果 deferred
被拒绝,http 请求则会失败。
响应拦截器的例子一样:
module.factory( 'myInterceptor' , [ '$q' , 'someAsyncService' , function ($q, someAsyncService) { var responseInterceptor = { 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 responseInterceptor; }]); |
只有当 deferred
被解析,请求才算成功,如果 deferred
被拒绝,请求将会失败。
例子
本节中我将提供一些 AngularJS 拦截器的例子,以便让你更好的理解它们是如何使用的,并且可以展示一下它们能怎样帮助你。不过请记住,我这里提供的解决案不一定是最好或者最准确的解决案。
Session 注入(请求拦截器)
这里有两种方式来实现服务端的认证。第一种是传统的 Cookie-Based
验证。通过服务端的 cookies 来对每个请求的用户进行认证。另一种方式是 Token-Based
验证。当用户登录时,他会从后台拿到一个 sessionToken
。sessionToken
在服务端标识了每个用户,并且会包含在发送到服务端的每个请求中。
下面的 sessionInjector
为每个被俘获的请求添加了 x-session-token
头 (如果当前用户已登录):
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' ); }]); |
然后创建一个请求:
|
被 sessionInjector
拦截之前的配置对象是这样的:
{ "transformRequest" : [ null ], "transformResponse" : [ null ], "method" : "GET" , "url" : "https://api.github.com/users/naorye/repos" , "headers" : { "Accept" : "application/json, text/plain, */*" } } |
被 sessionInjector
拦截之后的配置对象是这样的:
{ "transformRequest" : [ null ], "transformResponse" : [ null ], "method" : "GET" , "url" : "https://api.github.com/users/naorye/repos" , "headers" : { "Accept" : "application/json, text/plain, */*" , "x-session-token" : 415954427904 } } |
时间戳(请求和响应拦截器)
让我们用拦截器来测一下从后台返回响应需要多少时间。可以通过给每个请求和响应加上时间戳。
module.factory( 'timestampMarker' , [ function () { var timestampMarker = { request: function (config) { config.requestTimestamp = new Date().getTime(); return config; }, response: function (response) { response.config.responseTimestamp = new Date().getTime(); return response; } }; return timestampMarker; }]); module.config([ '$httpProvider' , function ($httpProvider) { $httpProvider.interceptors.push( 'timestampMarker' ); }]); |
然后我们可以这样:
$http.get( 'https://api.github.com/users/naorye/repos' ).then( function (response) { var time = response.config.responseTimestamp - response.config.requestTimestamp; console.log( 'The request took ' + (time / 1000) + ' seconds.' ); }); |
完整代码: example for the Timestamp Marker
请求恢复 (请求异常拦截)
为了演示请求异常拦截,我们需要模拟前一个拦截器拒绝了请求这种情况。我们的请求异常拦截器会拿到被拒绝的原因以及恢复请求。
让我们来创建两个拦截器: requestRejector
和 requestRecoverer
。
module.factory( 'requestRejector' , [ '$q' , function ($q) { var requestRejector = { request: function (config) { return $q.reject( 'requestRejector' ); } }; return requestRejector; }]); module.factory( 'requestRecoverer' , [ '$q' , function ($q) { var requestRecoverer = { requestError: function (rejectReason) { if (rejectReason === 'requestRejector' ) { // Recover the request return { transformRequest: [], transformResponse: [], method: 'GET' , headers: { Accept: 'application/json, text/plain, */*' } }; } else { return $q.reject(rejectReason); } } }; return requestRecoverer; }]); module.config([ '$httpProvider' , function ($httpProvider) { $httpProvider.interceptors.push( 'requestRejector' ); // Removing 'requestRecoverer' will result to failed request $httpProvider.interceptors.push( 'requestRecoverer' ); }]); |
然后,如果你像下面这样请求,我们会在 log 中看到 success
,虽然 requestRejector
拒绝了请求。
console.log( 'success' ); }, function (rejectReason) { console.log( 'failure' ); }); |
完整代码: example for the Request Recover
Session 恢复 (响应异常拦截器)
有时候,我们的单页面应用中,会发生丢失 session 情况。这种情况可能由于 session 过期了或者服务器异常。我们来创建一个拦截器,用于恢复 session 然后自动重新发送原始请求(假设 session 过期的情况)。
为了演示目的,我们来假设发生了 session 过期返回 http 状态码 419。
module.factory( 'sessionRecoverer' , [ '$q' , '$injector' , function ($q, $injector) { var sessionRecoverer = { responseError: function (response) { // Session has expired if (response.status == 419){ var SessionService = $injector.get( 'SessionService' ); var $http = $injector.get( '$http' ); var deferred = $q.defer(); // Create a new session (recover the session) // We use login method that logs the user in using the current credentials and // returns a promise SessionService.login().then(deferred.resolve, deferred.reject); // When the session recovered, make the same backend call again and chain the request return deferred.promise.then( function () { return $http(response.config); }); } return $q.reject(response); } }; return sessionRecoverer; }]); module.config([ '$httpProvider' , function ($httpProvider) { $httpProvider.interceptors.push( 'sessionRecoverer' ); }]); |
以这种方式,如果后台调用失败引起 session 过期,sessionRecoverer
会创建一个新的 session 然后重新调用后台。
(转)Angular中的拦截器Interceptor的更多相关文章
- Spring MVC中的拦截器Interceptor
谈谈spring中的拦截器 在web开发中,拦截器是经常用到的功能.它可以帮我们验证是否登陆.预先设置数据以及统计方法的执行效率等等.今天就来详细的谈一下spring中的拦截器.spring中拦截器主 ...
- springmvc中的拦截器interceptor用法
1.配置拦截器 在springMVC.xml配置文件增加: 1 <mvc:interceptors> 2 <!-- 日志拦截器 --> 3 <mvc:intercepto ...
- springMvc中实现拦截器Interceptor以及添加静态资源映射
这个代码写了很久了,多久呢?2018年12-20号写的.... 废话不多说,简化一下,作为笔记. 注: public class springmvcConfig extends WebMvcConfi ...
- struts2中方法拦截器(Interceptor)的中的excludeMethods与includeMethods的理解
http://www.cnblogs.com/langtianya/archive/2013/04/10/3012205.html
- 二十五、过滤器Filter,监听器Listener,拦截器Interceptor的区别
1.Servlet:运行在服务器上可以动态生成web页面.servlet的声明周期从被装入到web服务器内存,到服务器关闭结束.一般启动web服务器时会加载servelt的实例进行装入,然后初始化工作 ...
- JavaWeb—拦截器Interceptor
1.概念 java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取A ...
- SSM-SpringMVC-33:SpringMVC中拦截器Interceptor讲解
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 拦截器Interceptor: 对处理方法进行双向的拦截,可以对其做日志记录等 我选择的是实现Handler ...
- Java 中的过滤器Filter 和拦截器 Interceptor
1.先说拦截器 Interceptor 本项目以springboot为例: 新建 InterceptorConfig package com.opendev.mystudy.MyInterceptor ...
- Spring中过滤器(Filter)和拦截器(Interceptor)的区别和联系
在我们日常的开发中,我们经常会用到Filter和Interceptor.有时同一个功能.Filter可以做,Interceptor也可以做.有时就需要考虑使用哪一个比较好.这篇文章主要介绍一下,二者的 ...
随机推荐
- 【Java分享客栈】Java程序员为争一口气熬夜硬刚CSS实现掘金首页
前言 如果我做不了最厉害的Java工程师,那我就做Java工程师中最厉害的前端工程师. 前段时间,我默默给自己又喂了这碗心灵鸡汤-- 我不是很厉害的Java工程师,哪怕我已经工作八年,我依然觉得自己和 ...
- WinCE知识介绍
学习WinCE基本开发的步骤: 1.了解WinCE发展史: 2.WinCE开发环境搭建:[软件工具+插件] 3.简单案例: 参考:http://blog.csdn.net/educast/articl ...
- 西门子S210电机位置控制过调问题解决方法
问题描述 创建完工艺对象,使用MC_MoveAbsolute工艺指令进行绝对定位,发现在下达指令后,电机会出现先超过目标位置再回调的现象,即过冲. 电机连接的机械结构为旋转轴,而不是线性轴. 解决方法 ...
- sftp服务器搭建以及挂载新硬盘到home目录下
前言 我身边一直有一个空闲不用的硬盘,一直空闲不用,闲暇的时候想到为什么不用起来呢,于是想起来搭建一个sftp服务器,当做云盘用了 搭建sftp服务器 SFTP称作"安全的FTP" ...
- 服务端处理 Watcher 实现 ?
1.服务端接收 Watcher 并存储 接收到客户端请求,处理请求判断是否需要注册 Watcher,需要的话将数据节点 的节点路径和 ServerCnxn(ServerCnxn 代表一个客户端和服务端 ...
- 学习Cobbler(二)
Server端: 第一步,启动Cobbler服务 第二步,进行Cobbler错误检查,执行cobbler check命令 第三步,进行配置同步,执行cobbler sync命令 第四步,复制相关启动文 ...
- 前端网络安全——前端CSRF
CSRF:Cross Site Request Forgy(跨站请求伪造) 用户打开另外一个网站,可以对本网站进行操作或攻击.容易产生传播蠕虫. CSRF攻击原理: 1.用户先登录A网站 2.A网站确 ...
- 【每日日报】第三十二天---DataOutputStream写文件
1 今天继续看书 DataOutputStream写文件 1 package File; 2 import java.io.IOException; 3 import java.io.FileOutp ...
- java中抽象类和抽象方法到底什么关系?请举例说明!
抽象类和抽象方法什么关系?抽象类中可能有抽象方法,也可能没有抽象方法.那位说,就跟没说一样,那抽象类和抽象方法都叫抽象,他们必定有关系,那关系是什么呢?如果一个类中有抽象方法,它必须得是抽象类. An ...
- 用Python爬取斗鱼网站的一个小案例
思路解析: 1.我们需要明确爬取数据的目的:为了按热度查看主播的在线观看人数 2.浏览网页源代码,查看我们需要的数据的定位标签 3.在代码中发送一个http请求,获取到网页返回的html(需要注意的是 ...