(转)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也可以做.有时就需要考虑使用哪一个比较好.这篇文章主要介绍一下,二者的 ...
随机推荐
- windows 2008 R2磁盘清理
记录一次由于磁盘空间满,IIS使前端程序报500的事故 由于导出Api部署在IIS服务器,在程序调用导出Api会报500 发现windows服务器C盘已满 下面处理过程 只需复制cleanmgr.ex ...
- Linux下使用Google Authenticator配置SSH登录动态验证码
1.一般ssh登录服务器,只需要输入账号和密码.2.本教程的目的:在账号和密码之间再增加一个验证码,只有输入正确的验证码之后,再输入密码才能登录.这样就增强了ssh登录的安全性.3.账号.验证码.密码 ...
- FPGA驱动LCD显示红绿蓝彩条
实验目的:先简单熟悉LCD灯的驱动和时序图的代码实现.设计功能是让LCD显示红绿蓝三种颜色,即三个彩带.本次实验比较容易实现,主要是对LCD驱动时序图的理解和时序参数的配置. 实验条件:1.LCD原理 ...
- oracle.i18n.text.convert.CharacterConverterOGS.getInstance(I)Loracle/i18n/text/converter/CharacterConver;
看看项目是不是同时包含ojdbc系列jar包和nls_charset12.jar包.如果同时包含,则删除nls_charset12.jar.因为低版本的nls_charset12和ojdbc包冲突.
- 如何给Spring 容器提供配置元数据?
这里有三种重要的方法给Spring 容器提供配置元数据. XML配置文件. 基于注解的配置. 基于java的配置.
- 两个相同的对象会有不同的的 hash code 吗?
不能,根据 hash code 的规定,这是不可能的.
- 学习openldap01
Linux 下openldap的详细介绍,搭建,配置管理,备份,案例 Ldap 服务应用指南 兼容(5.X&6.X) 1.1 Ldap 目录服务介绍 1.1.1 什么是目录服务(activ ...
- BMZCTF 2020祥云杯到点了
2020祥云杯到点了 下载附件得到三个word文档,我们打开第一个文档然后将隐藏文字显示出来 得到提示 我们查看属性应该就是日期了我们先把他记录下来 然后打开第二个文档 输入刚刚的密码 在第二个wor ...
- C 语言中 static 的作用
在 C 语言中,static 的字面意思很容易把我们导入歧途,其实它的作用有三条. (1)先来介绍它的第一条也是最重要的一条:隐藏 当我们同时编译多个文件时,所有未加 static 前缀的全局变量和函 ...
- zookeeper操作节点代码
package cn.hbaf.zookeeper_api; import org.apache.curator.RetryPolicy; import org.apache.curator.fram ...