在本篇内容中,我们将着重于ajax和承诺的实例当中,至于原理会在案例中一同讲解,其实原理也没什么好讲的,无非是几个api的应用,这里重在实践。
案例一:通过ajax的get请求JSON数据,获取产品的数据,并以表格的形式展现出来
准备数据 productData.json文件
[{ "name": "Apples","category": "Fruit","price": 1.20,"expiry": 10 },{ "name": "Bananas","price": 2.42,"expiry": 7 },{ "name": "Pears","price": 2.02,"expiry": 6 },{ "name": "Tuna","category": "Fish","price": 20.45,"expiry": 3 },{ "name": "Salmon","price": 17.93,"expiry": 2 },{ "name": "Trout","price": 12.93,"expiry": 4 }]
发送和接受 ajax 响应文件
<!DOCTYPE> <!-- use module --> <html ng-app="exampleApp"> <head> <title>Angluar ajax</title> <Meta charset="utf-8"/> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> </head> <body ng-controller="defaultCtrl"> <div class="panel panel-default"> <div class="panel-body"> <table class="table table-striped table-hover"> <thead> <tr> <th>水果名</th> <th>类别</th> <th>价格</th> <th>保质期</th> </tr> </thead> <tbody> <tr ng-hide="products.length"> <td colspan="4" class="text-center">没有数据</td> </tr> <tr ng-repeat="item in products"> <td>{{item.name}}</td> <td>{{item.category}}</td> <td>{{item.price | currency}}</td> <td>{{item.expiry}}天</td> </tr> </tbody> </table> <p> <button class="btn btn-primary" ng-click="loadData()">加载数据</button> </p> </div> </div> <script type="text/javascript" src="js/angular.min.js"></script> <!-- 引入指令文件 --> <script type="text/javascript"> // 使用指令 angular.module("exampleApp",[]) .controller("defaultCtrl",function ($scope,$http) { // 数据模型 $scope.loadData = function () { $http.get("productData.json").success(function (data) { $scope.products = data; }); } }) </script> </body> </html>
案例解析:
第一步:准备要解析的 JSON 数据文件
第二步:通过
get(url,config) 为指定 URL 执行 GET 请求
post(url,data,config) 为指定 URL 执行 POST 请求提交指定数据
delete(url,config) 为指定 URL 执行 DELETE 请求
put(url,config) 为指定 URL 和数据执行 PUT 请求
head(url,config) 为指定 URL 执行 HEAD 请求
jsonp(url,config) 执行 GET 请求获取 JS 代码片段然后执行该代码
第三步:通过 success() 方法接受 Ajax 响应
下面是由 $http 服务方法返回的承诺对象所定义的方法
success(fn) 当 HTTP 请求成功完成时,调用指定函数 error(fn) 当请求无法成功完成时,调用指定函数 then(fn,fn) 注册成功函数和失败函数
第四步:了解返回承诺对象参数的细节
data 从请求中返回的数据
status 返回由服务器返回的 HTTP 状态码
headers 返回可被用于获取名为头部的函数
config 用于产生请求的配置对象
点击”加载数据“按钮,发送 ajax 请求,并且将数据以表格的形式展示
案例二:通过ajax的get请求XML数据,获取产品的数据,并以表格的形式展现出来
要请求的xml数据
<products>
<product name="Apples" category="Fruit" price="1.20" expiry="10" />
<product name="Bananas" category="Fruit" price="2.42" expiry="7" />
<product name="Pears" category="Fruit" price="2.02" expiry="10" />
<product name="Tuna" category="Fish" price="20.45" expiry="3" />
<product name="Salmon" category="Fish" price="17.93" expiry="2" />
<product name="Trout" category="Fish" price="12.93" expiry="4" />
</products>
通过$http 和 jqlite 来产生数据
<!DOCTYPE> <!-- use module --> <html ng-app="exampleApp"> <head> <title>Angluar ajax</title> <Meta charset="utf-8"/> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> </head> <body ng-controller="defaultCtrl"> <div class="panel panel-default"> <div class="panel-body"> <table class="table table-striped table-hover"> <thead> <tr> <th>水果名</th> <th>类别</th> <th>价格</th> <th>保质期</th> </tr> </thead> <tbody> <tr ng-hide="products.length"> <td colspan="4" class="text-center">没有数据</td> </tr> <tr ng-repeat="item in products"> <td>{{item.name}}</td> <td>{{item.category}}</td> <td>{{item.price | currency}}</td> <td>{{item.expiry}}天</td> </tr> </tbody> </table> <p> <button class="btn btn-primary" ng-click="loadData()">加载数据</button> </p> </div> </div> <script type="text/javascript" src="js/angular.min.js"></script> <!-- 引入指令文件 --> <script type="text/javascript"> // 使用指令 angular.module("exampleApp",$http) { // 数据模型 $scope.loadData = function () { // 获取xml文件的内容 $http.get("productData.xml").then(function (response) { // 定义的对象数组 $scope.products = []; // 在xml dom 中找出product标签 var productElems = angular.element(response.data.trim()).find("product"); // 遍历product中的内容,将数据全部保存到数组中去 for (var i = 0; i < productElems.length; i++) { var product = productElems.eq(i); $scope.products.push({ name : product.attr("name"),category : product.attr("category"),price : product.attr("price"),expiry : product.attr("expiry"),}); } }); } }) </script> </body> </html>
样式和案例一相同,这里不再截图展示
案例三:配置 Ajax 请求—通过config来配置发送和请求的信息
<!DOCTYPE> <!-- use module --> <html ng-app="exampleApp"> <head> <title>Angluar ajax</title> <Meta charset="utf-8"/> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> </head> <body ng-controller="defaultCtrl"> <div class="panel panel-default"> <div class="panel-body"> <table class="table table-striped table-hover"> <thead> <tr> <th>水果名</th> <th>类别</th> <th>价格</th> <th>保质期</th> </tr> </thead> <tbody> <tr ng-hide="products.length"> <td colspan="4" class="text-center">没有数据</td> </tr> <tr ng-repeat="item in products"> <td>{{item.name}}</td> <td>{{item.category}}</td> <td>{{item.price | currency}}</td> <td>{{item.expiry}}天</td> </tr> </tbody> </table> <p> <button class="btn btn-primary" ng-click="loadData()">加载数据</button> <button class="btn btn-primary" ng-click="sendData()">发送数据</button> </p> </div> </div> <script type="text/javascript" src="js/angular.min.js"></script> <!-- 引入指令文件 --> <script type="text/javascript"> // 使用指令 angular.module("exampleApp",$http) { // 数据模型 $scope.loadData = function () { $http.get("productData.json").success(function (data) { // 获取json数据 $scope.products = data; }); } $scope.sendData = function () { // 配置发送信息 var config = { // 设置请求头部--请求类型为xml headers : { "content-type" : "application/xml" },// 在请求发送到服务器前操作---这里产生xml数据 transformRequest : function (data,headers) { var rootElem = angular.element("<xml>"); for (var i = 0; i < data.length; i++) { var productEle = angular.element("<product>"); productEle.attr("name",data[i].name); productEle.attr("category",data[i].category); productEle.attr("price",data[i].price); productEle.attr("expiry",data[i].expiry); rootElem.append(productEle); } rootElem.children().wrap("<products>"); return rootElem.html(); } } // 将配置文件中产生的xml文件,发送到defaultAjax.html中 $http.post("defaultAjax.html",$scope.products,config).success(function (data) { console.log(data); }); } }) </script> </body> </html>
案例解析:
点击”加载数据“,从json文件中读取数据;点击”发送数据“,将数据转换为xml
<!DOCTYPE> <!-- use module --> <html ng-app="exampleApp"> <head> <title>Angluar ajax</title> <Meta charset="utf-8"/> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> </head> <body ng-controller="defaultCtrl"> <div class="panel panel-default"> <div class="panel-body"> <table class="table table-striped table-hover"> <thead> <tr> <th>水果名</th> <th>类别</th> <th>价格</th> <th>保质期</th> </tr> </thead> <tbody> <tr ng-hide="products.length"> <td colspan="4" class="text-center">没有数据</td> </tr> <tr ng-repeat="item in products"> <td>{{item.name}}</td> <td>{{item.category}}</td> <td>{{item.price | currency}}</td> <td>{{item.expiry}}天</td> </tr> </tbody> </table> <p> <button class="btn btn-primary" ng-click="loadData()">加载数据</button> </p> </div> </div> <script type="text/javascript" src="js/angular.min.js"></script> <!-- 引入指令文件 --> <script type="text/javascript"> // 使用指令 angular.module("exampleApp",$http) { $scope.loadData = function () { $http.get("doesnotexit.json").success(function (data) { $scope.products = data; }); } }) .config(function ($httpProvider) { $httpProvider.interceptors.push(function () { return { request : function (config) { // 更改url config.url = "productData.json"; return config; },response : function (response) { console.log("Data Count: " + response.data.length); return response; } } }) }) </script> </body> </html>
案例解析:将$http.get请求的URL(doesnotexit.json)拦截下来修改为productData.json
承诺的使用
承诺是$q
服务来完成的,NG提供$q
服务来管理和获取承诺
1.下面是由$q
服务定义的方法
all(promises) 当指定的数组中的所有承诺被解决或其中任意一个被拒绝返回承诺 defer() 创建发送通知的对象 reject(reason) 返回始终被拒绝的承诺 when(value) 在总能被解决的承诺中封装一个值
2.获取和使用Defered 对象
resolve(result) 带有指定值的延迟活动完成的信号 reject(reason) 延迟活动失败了的信号 notify(result) 提供来自延迟活动的临时结果 promise 返回接收其他方法信号的承诺对象
3.Promise 对象定义的方法
then(success,error,notify) 注册被调用的函数以响应defered对象的 resolve、reject 和 notify 方法
catch(error) 注册仅用于错误的处理函数
finally(fn) 注册无论承诺是否被解决调用的函数
案例五:承诺的使用
<!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar ajax</title>
<Meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
</head>
<body ng-controller="defaultCtrl">
<div class="well" promise-worker>
<button class="btn btn-primary">Heads</button>
<button class="btn btn-primary">Tails</button>
<button class="btn btn-primary">Abort</button>
Outcome: <span promise-observer></span>
</div>
<script type="text/javascript" src="js/angular.min.js"></script>
<!-- 引入指令文件 -->
<script type="text/javascript"> // 使用指令 angular.module("exampleApp",$http) { $scope.loadData = function () { } }) .directive("promiseWorker",function ($q) { // 创建defered对象,用于发送通知 var deferred = $q.defer(); return { link : function (scope,element,attrs) { element.find("button").on("click",function (e) { var btnTxt = e.target.innerText; // console.log(btnTxt); if (btnTxt == 'Abort') { // 返回失败信号 deferred.reject('Aborted'); } else { // 返回完成信号 deferred.resolve(btnTxt); } }) },// 承诺特征: // 1. 用完就扔掉,即第二次不会触发 // 2. 发出结果和产生信号 controller : function ($scope,$element,$attrs) { // 返回接收亲她方法信号的promise对象 this.promise = deferred.promise; } } }) .directive("promiSEObserver",function () { return { require : "^promiseWorker",link : function (scope,attrs,ctrl) { ctrl.promise.then(function (result) { element.text(result); },function (reason) { element.text("Fail (" + reason + ")"); }) } } }) </script>
</body>
</html>
案例解析:
点击前两个按钮,发送承诺完成的信号;点击最后一个按钮,发送承诺没完成的信号
案例六:分组承诺
当你想执行一系列的动作时,承诺链就很有用,但是还是要分场合的,比如你想延迟活动直到其他的结果可用。$q.all
方法,它接受承诺的数组并返回在所有输出的承诺被解决前不会解决的承诺
<!DOCTYPE>
<!-- use module -->
<html ng-app="exampleApp">
<head>
<title>Angluar ajax</title>
<Meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
</head>
<body ng-controller="defaultCtrl">
<div class="well" promise-worker>
<div class="btn-group">
<button class="btn btn-primary" data-group="0">Heads</button>
<button class="btn btn-primary" data-group="0">Tails</button>
<button class="btn btn-primary" data-group="0">Abort</button>
</div>
<div class="btn-group">
<button class="btn btn-primary" data-group="1">Yes</button>
<button class="btn btn-primary" data-group="1">No</button>
<button class="btn btn-primary" data-group="1">Abort</button>
</div>
Outcome: <span promise-observer></span>
</div>
<script type="text/javascript" src="js/angular.min.js"></script>
<!-- 引入指令文件 -->
<script type="text/javascript"> // 使用指令 angular.module("exampleApp",function ($scope) { }) .directive("promiseWorker",function ($q) { var deferred = [$q.defer(),$q.defer()]; var promises = [deferred[0].promise,deferred[1].promise]; return { link : function (scope,function (e) { var btnTxt = e.target.innerText; var buttonGroup = e.target.getAttribute("data-group"); // console.log(btnTxt); if (btnTxt == 'Abort') { deferred[buttonGroup].reject('Aborted'); } else { deferred[buttonGroup].resolve(btnTxt); } }) },$attrs) { // $q.all 当指定的数组中的所有承诺被解决或者其中任意一个被拒绝时返回承诺 this.promise = $q.all(promises).then(function (results) { console.log(results.join()); return results.join(); }) } } }) .directive("promiSEObserver",function (reason) { element.text("Fail (" + reason + ")"); }) } } }) </script>
</body>
</html>
单击Heads 和 Yes 之后,才返回信号