在AngularJS中,与服务器交互的能力同样依赖于XMLHttpRequest对象实现。正如在JS中一样,AngularJS对XMLHttpRequest对象进行了封装,使得开发者能以更优雅的方式与服务器进行Ajax交互。
$http是AngularJS内置的一个Ajax支持的服务。与该服务配套使用的,还有如下常用的服务。
1. $httpParamSerializer:该服务用于将JS对象转换为查询字符串。
2.$httpParamSerializerJQLike:该服务用于将JS对象转换为查询字符串。该服务与上一个服务的细微区别是,它转换为的查询字符串更符合jQuery风格。
3.$xhrFactory:一般不直接使用该服务。当开发者对AngularJS创建的XMLHttpRequest对象的方式不满意时,开发者可替换或修改该服务,从而创建自己的XMLHttpRequest对象.(一般来说,开发者没必要替换或修改$xhrFactory服务。)
接下来我们通过一个例子来看一下上述的服务是如何运用的:
<body ng-app="httpExample" ng-strict-di>
<div ng-controller="fkCtrl">
输入用户名<input type="text" ng-model="user.name" /><br/>
输入密码:<input type="text" ng-model="user.pass" /><br/>
$httpParamSerializer:{{serializer1}}<br />
$httpParamSerializerJQLike:{{serializer2}}<br />
</div>
<script type="text/javascript">
var app=angular.module("httpExample",[])
.controller("fkCtrl",['$scope','$httpParamSerializer','$httpParamSerializerJQLike',function($scope,$httpParamSerializer,$httpParamSerializerJQLike){
$scope.user={pass:'123456',name:'yeeko'};
$scope.serializer1=$httpParamSerializer($scope.user);
$scope.serializer2=$httpParamSerializerJQLike($scope.user);
}]);
</script>
</body>
$http服务调用它的构造器即可与服务器交互,调用构造器时只要传入一个JS对象指定与服务器交互的选项即可。该JS对象支持如下属性。(仅列举常用的)
method:该属性指定发送请求的方式,该属性支持GET,POST等请求。
url:该属性指定发送请求的URL地址。
data:该属性指定请求参数。
headers:该属性指定发送请求的请求头。该属性应该是一个JS对象,对象的属性名表示请求头的名,属性值表示请求头的值。
调用$http服务的构造器将会返回一个Promise对象(简单来说就是一个容器,里面保存着在某个未来才会结束的事件的结果,是异步编程的一种解决方案。)接下来程序可调用该对象的then()方法传入resolve、reject回调函数,这两个回调函数相当于Ajax的交互成功、失败的回调函数。两个回调函数都支持一个response参数。下面示例示范了如何使用$http服务与服务器进行交互。
<script type="text/javascript" src="angular-1.6.2.js">
</script>
<script type="text/javascript" src="angular-sanitize.min.js">
</script>
</head>
<body ng-app="ajaxModule">
<div ng-controller="fkCtrl">
<h3>请输入你的信息</h3>
<form id="userForm">
用户名:<input type="text" name="user" ng-model="params.user" /><br />
喜欢的图书:<select multiple="multiple" name="books" ng-model="params.books">
<option value="java">疯狂java讲义</option>
<option value="javaee">轻量级Java EE企业实战</option>
<option value="ajax">疯狂前端开发讲义</option>
<option value="xml">疯狂XML讲义</option>
</select><br />
<input type="button" id="load" value="发送异步请求" ng-click="send();"/>
</form><hr />
<div ng-bind-html="show"></div>
</div>
<script type="text/javascript">
angular.module("ajaxModule",['ngSanitize'])
.controller('fkCtrl',['$scope','$http','$httpParamSerializer',function($scope,$http,$httpParamSerializer){
$scope.send=function(){
$http({
method:"POST",
url:'pro',
data:&httpParamSerializer($scope.params),
headers:{
'Content-Type':'application/x-www-form-urlencoded'
}
}).then(function successCallback(response)
{
$scope.show="服务器响应状态为:"+response.status+"<br />"
+response.data;
},function errorCallback(response){
$scope.show='服务器响应异常';
});
};
}]);
</script>
</body>
接下来是需要搭建服务器以及编写服务器端的脚本,在这里我就不细说了。
$http服务还提供了如下快捷方法与服务器进行交互,这些方法都是对$http的简化。
1.$http.get(url,[config]):发送GET请求的快捷方法
2.$http.head(url,[config]):发送HEAD请求的快捷方法
3.$http.post(url,data,[config]):发送POST请求的快捷方法
4.$http.put(url,data,[config]):发送PUT请求的快捷方法
5.$http.head(url,[config]):发送HEAD请求的快捷方法
6.$http.delete(url,[config]):发送delete请求的快捷方法
7.$http.jsonp(url,[config]):发送JSONP请求的快捷方法
8.$http.patch(url,data,[config]):发送JSONP请求的快捷方法
在这些方法中都可指定一个config参数,该参数的作用和直接使用$http时传入的config参数的作用相同。
下面示范了使用快捷方法$http.post()发送POST请求:
<script type="text/javascript" src="angular-1.6.2.js">
</script>
<script type="text/javascript" src="angular-sanitize.min.js">
</script>
</head>
<body ng-app="ajaxModule">
<div ng-controller="fkCtrl">
<h3>请输入你的信息</h3>
<form id="userForm">
用户名:<input type="text" name="user" ng-model="params.user" /><br />
喜欢的图书:<select multiple="multiple" name="books" ng-model="params.books">
<option value="java">疯狂java讲义</option>
<option value="javaee">轻量级Java EE企业实战</option>
<option value="ajax">疯狂前端开发讲义</option>
<option value="xml">疯狂XML讲义</option>
</select><br />
<input type="button" id="load" value="发送异步请求" ng-click="send();"/>
</form><hr />
<div ng-bind-html="show"></div>
</div>
<script type="text/javascript">
angular.module("ajaxModule",['ngSanitize'])
.config(function($httpProvider){
$httpProvider.default.headers.post['Content-Type']='application/x-www-form-urlencoded';
}) //该例与前面介绍的使用$http与服务器进行交互的代码区别在于此,挂断代码为整个模块进行了配置,为所有的post请求增加了Content-Type请求头,经过这样设置后,AngularJS在提交Post请求时,总会将Content-Type请求头设为'application/x-www-form-urlencoded';这样就不需要每次提交POST请求时都通过config进行设置了。
.controller('fkCtrl',['$scope','$http','$httpParamSerializer',function($scope,$http,$httpParamSerializer){
$scope.send=function(){
$http.post('pro',$httpParamSerializer($scope.params))
.then(function successCallback(response)
{
$scope.show="服务器响应状态为:"+response.status+"<br />"
+response.data;
},function errorCallback(response){
$scope.show='服务器响应异常';
});
};
}]);
</script>
</body>
使用$http上传文件:
使用$http上传文件有两个关键点:
1.将表单内的文件以二进制的方式提交,这一点可借助于FormData来实现,因此只要在使用$http提交请求时将FormData设为请求参数即可。
2.不能以application/x-www-form-urlencoded方式提交请求,要以multipart/form-data的方式提交请求。实际上提价请求时不能将Content-Type请求头设为multipart/form-data,而是应该将请求头设为undefined,让AngularJS根据请求参数自动添加Content-Type请求头。
下面的代码示范了如何利用$http处理文件上传。
<script type="text/javascript" src="angular-1.6.2.js">
</script>
<script type="text/javascript" src="angular-sanitize.min.js">
</script>
</head>
<body ng-app="ajaxModule">
<div ng-controller="fkCtrl">
<form id="bookForm">
书名:<input type="text" name="name"/><p>
价格:<input type="text" name="price"/><p>
作者:<input type="text" name="author"/><p>
出版时间:<input type="month" name="publishDate"/><p>
图书封面:<input type="file" name="cover" accept="image/*"/><p>
<button type="button" ng-click="send();">提交</button>
</form>
<progress id="prog" min="0" max="100" ng-show="prog<100" value='{{prog}}'></progress>
<div ng-bind-html="show"></div>
</div>
<script type="text/javascript">
angular.module("ajaxModule",['ngSanitize'])
.controller("fkCtrl",['$scope','$http',function($scope,$http){
$scope.prog=100;
$scope.send=function(){
var formData=new FormData(document.querySelector("#bookForm"));
$http({url:'second.jsp',data:formData,method:'POST',headers:{
'Content-Type':undefined},
uploadEventHandlers:{
progress:function(e){
$scope.$apply(function(){
$scope.prog=(e.loaded/e.total)*100;
})
}
}
])
.then(function successCallback(response)
{
$scope.show="服务器响应状态为:"+response.status+"<br />"
+response.data;
},function errorCallback(response){
$scope.show='服务器响应异常';
});
};
}]);
</script>
</body>
使用$resource服务:
AngularJS还提供了一个ngResource模块,该模块专门用于支持RESTful风格的服务交互。(关于RESTFUL风格:客户端和服务器之间的交互在请求之间是无状态的,无状态的请求可以由任何可用服务器回答,这十分适合云计算之类的环境,客户端可以缓存数据以改进性能)。
由于ngResource模块并不是AngularJS的核心部分,而是一个可选的模块,因此如果需要使用该模块,则需要在页面上单独引用该模块的JS库。
引入该模块之后,接下来即可使用$resource服务了。使用$resource服务大致可分为两步:
1.调用$resource(url,[paramDefaults],[actions],options)构造器创建一个对象。
程序并不直接使用$resource与服务器通信,$resource是一个创建资源对象的工厂,用来创建同服务器端交互的对象。
var CreditCard=$resource('/user/:userId/card/:cardId',{userId:123,cardId:'@id');
以上代码返回的CreditCard对象包含了同后端服务进行交互的方法,因此可将CreditCard对象理解成与RESTful服务通信的接口。
2.调用通信对象的get,save,query,remove,delete方法与服务器交互。eg:{‘get’:{method:'GET'}}
eg:
var CreditCard=$resource('/user/:userId/card/:cardId',{userId:123,cardId:'@id');
var card=CreditCard.get({cardId:20},function(){...});