AngularJS XMLHttpRequest
AngularJS XMLHttpRequest (HTTP 请求) 学习笔记
在 AngularJS 中,$http服务是处理 XMLHttpRequest (XHR) 的核心工具。它封装了原生的XMLHttpRequest对象,提供了基于Promise的异步 API,并集成了拦截器、转换器和自动的 CSRF 保护。
一、核心概念:$http服务
1. 什么是$http?
- 定义:AngularJS 内置服务,用于与远程服务器进行 HTTP 通信。
- 原理:底层封装了原生的
XMLHttpRequest或JSONP。 - 返回值:返回一个Promise对象(基于
$q服务),支持.then()链式调用。 - 自动处理:
- 自动解析 JSON 响应。
- 自动设置
Content-Type头。 - 自动处理 CSRF Token(如果配置了)。
2. 基本用法
app.controller('MyCtrl',function($scope,$http){// GET 请求$http.get('/api/users').then(function(response){// 成功回调$scope.users=response.data;}).catch(function(error){// 错误回调console.error('Error:',error.status,error.statusText);});});二、HTTP 方法详解
$http支持所有标准的 HTTP 方法,每个方法都返回一个 Promise。
1.GET- 获取数据
$http.get('/api/users',{params:{page:1,size:10}// 自动转换为查询字符串 ?page=1&size=10}).then(function(response){$scope.users=response.data;});2.POST- 提交数据
$http.post('/api/users',{name:"John",age:25}).then(function(response){$scope.message="用户创建成功";});3.PUT- 更新数据
$http.put('/api/users/1',{name:"Jane",age:26}).then(function(response){$scope.message="用户更新成功";});4.DELETE- 删除数据
$http.delete('/api/users/1').then(function(response){$scope.message="用户删除成功";});5.PATCH- 部分更新
$http.patch('/api/users/1',{age:27}).then(function(response){// 处理响应});6.JSONP- 跨域请求
// 注意:JSONP 需要服务器支持 callback 参数$http.jsonp('/api/users?callback=JSONP_CALLBACK').then(function(response){$scope.users=response.data;});三、请求配置对象 (Config Object)
所有 HTTP 方法都接受一个可选的配置对象,用于自定义请求行为。
$http({method:'POST',// 请求方法url:'/api/users',// 请求 URLheaders:{// 自定义请求头'Content-Type':'application/json','Authorization':'Bearer token123'},params:{// GET 请求的查询参数page:1,size:10},data:{// POST/PUT 的请求体name:"John",age:25},timeout:5000,// 超时时间(毫秒)transformRequest:[],// 自定义请求数据转换函数transformResponse:[],// 自定义响应数据转换函数cache:true,// 启用缓存withCredentials:true// 允许发送 Cookie}).then(successCallback,errorCallback);常用配置项详解:
headers:设置自定义 HTTP 头(如 Token、Content-Type)。params:自动附加到 URL 的查询参数(GET 请求)。data:请求体数据(POST/PUT/PATCH)。timeout:请求超时时间,超过则自动取消。cache:true:使用$http默认缓存。false:禁用缓存。CacheService:使用自定义缓存服务。
withCredentials:跨域请求时携带 Cookie(需服务器支持 CORS)。
四、响应对象结构
$http的 Promise 成功回调接收一个响应对象,包含以下属性:
$http.get('/api/users').then(function(response){// response.data: 响应体(已自动解析 JSON)// response.status: HTTP 状态码 (200, 404, 500...)// response.headers: 响应头获取函数// response.config: 原始请求配置对象// response.statusText: 状态文本 ("OK", "Not Found")console.log(response.data);console.log(response.status);});错误响应
$http.get('/api/users').catch(function(response){// response.status: 错误状态码 (404, 500...)// response.data: 错误信息// response.statusText: 错误文本// response.config: 原始请求配置});五、快捷方法 vs 通用方法
| 方法 | 语法 | 适用场景 |
|---|---|---|
| 快捷方法 | $http.get(),$http.post() | 简单请求,代码简洁 |
| 通用方法 | $http({ method: '...', ... }) | 复杂配置(自定义头、超时、转换器等) |
示例对比:
// 快捷方法$http.get('/api/users',{params:{id:1}});// 通用方法(功能相同)$http({method:'GET',url:'/api/users',params:{id:1}});六、拦截器 (Interceptors)
拦截器是$http的强大功能,允许在请求发送前或响应返回后全局拦截和修改数据。
1. 定义拦截器
app.factory('HttpInterceptor',function($q,$injector){return{// 请求拦截器request:function(config){// 添加 Tokenconfig.headers['Authorization']='Bearer '+localStorage.getItem('token');returnconfig;},// 请求错误拦截器requestError:function(rejection){console.error('请求错误:',rejection);return$q.reject(rejection);},// 响应拦截器response:function(response){// 处理成功响应if(response.status===200){// 可以修改响应数据}returnresponse;},// 响应错误拦截器responseError:function(rejection){// 统一处理错误(如 401 跳转登录)if(rejection.status===401){// 跳转到登录页window.location.href='/login';}return$q.reject(rejection);}};});2. 注册拦截器
app.config(function($httpProvider){$httpProvider.interceptors.push('HttpInterceptor');// 或者推入函数$httpProvider.interceptors.push(function($q){return{request:function(config){...}};});});3. 典型应用场景
- 统一添加 Token:在
request中注入 JWT。 - 全局错误处理:在
responseError中处理 401/403/500。 - 请求加载动画:在
request中显示 Loading,response中隐藏。 - 数据转换:统一格式化请求/响应数据。
七、请求取消 (Cancelling Requests)
AngularJS 支持取消未完成的 HTTP 请求,防止内存泄漏和无效请求。
1. 使用timeout配置
varcanceler=$q.defer();$http.get('/api/users',{timeout:canceler.promise}).then(function(response){// 处理响应});// 取消请求canceler.resolve();2. 在控制器销毁时取消
app.controller('UserCtrl',function($scope,$http,$q){varcanceler=$q.defer();$http.get('/api/users',{timeout:canceler.promise}).then(function(response){$scope.users=response.data;});// 控制器销毁时取消请求$scope.$on('$destroy',function(){canceler.resolve();});});八、CSRF 保护
AngularJS 自动处理 CSRF(跨站请求伪造)保护。
1. 配置
- 默认从 Cookie 读取
XSRF-TOKEN。 - 自动在请求头中添加
X-XSRF-TOKEN。 - 配置项:
$httpProvider.defaults.xsrfCookieName和$httpProvider.defaults.xsrfHeaderName。
app.config(function($httpProvider){$httpProvider.defaults.xsrfCookieName='XSRF-TOKEN';$httpProvider.defaults.xsrfHeaderName='X-XSRF-TOKEN';});2. 后端配合
- 后端需设置
XSRF-TOKENCookie。 - 后端需验证请求头中的
X-XSRF-TOKEN。
九、最佳实践
1. 封装 API 服务
不要直接在控制器中写$http,应封装到 Service 中。
// services/api.jsapp.factory('UserService',function($http){return{getAll:function(){return$http.get('/api/users');},getById:function(id){return$http.get('/api/users/'+id);},create:function(user){return$http.post('/api/users',user);}};});// 控制器中使用app.controller('UserCtrl',function($scope,UserService){UserService.getAll().then(function(res){$scope.users=res.data;});});2. 统一错误处理
使用拦截器统一处理错误,避免在每个控制器中重复写catch。
3. 避免内存泄漏
- 在
$destroy事件中取消未完成的请求。 - 避免在循环中发起大量请求(使用防抖或节流)。
4. 使用 Promise 链
// ✅ 好:链式调用UserService.getAll().then(function(res){$scope.users=res.data;returnUserService.getStats();}).then(function(stats){$scope.stats=stats.data;}).catch(function(error){console.error('Error:',error);});5. 处理大文件上传
使用FormData和transformRequest: angular.identity。
varformData=newFormData();formData.append('file',fileInput.files[0]);$http.post('/api/upload',formData,{headers:{'Content-Type':undefined},transformRequest:angular.identity});十、常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 跨域错误 (CORS) | 服务器未配置 CORS 头 | 服务器添加Access-Control-Allow-Origin |
| CSRF 失败 | Cookie 或 Header 名称不匹配 | 检查$httpProvider配置和后端设置 |
| 数据未更新 | 异步回调中未触发$apply | 使用 Promise 或$timeout |
| 请求被取消 | 组件销毁时未清理 | 在$destroy中调用canceler.resolve() |
| JSON 解析失败 | 响应不是标准 JSON | 检查transformResponse或服务器返回格式 |
| 重复请求 | 快速点击导致多次提交 | 使用防抖或禁用按钮 |
十一、总结
AngularJS$http服务的核心要点:
- Promise 基础:所有请求返回 Promise,支持
.then()和.catch()。 - 配置灵活:支持自定义头、参数、超时、缓存等。
- 拦截器强大:全局处理请求/响应,统一添加 Token、处理错误。
- 自动处理:JSON 解析、CSRF 保护、错误状态码。
- 封装原则:将
$http封装到 Service,控制器只负责业务逻辑。 - 资源清理:在组件销毁时取消未完成的请求,防止内存泄漏。
通过合理使用$http和拦截器,可以构建出健壮、可维护的异步数据交互层。
