angularjs提供的$q服务是对Promises规范的一个实现。$q服务可以把一段异步的代码封装成同步的样式。
为啥是样式,因为异步还是异步,它并不会柱塞代码,只是看起来像同步代码。
$q.when('abc').then().then();
下面的代码演示了$q的构造函数的使用方法。$q的构造函数接受一个function(resolve,reject)的函数,resolve是成功的回掉,reject是失败的回掉。
通常Ajax请求都是异步的,通过success,failed回掉来处理结果。通过$q服务我们可以把这个ajax请求改写成promise的形式。
当然这个接口是我通过$timeout服务模拟了一个2s回复的ajax请求。
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body ng-app="app" ng-controller="ctrl" >
<style>
.valid-error{
color:red
}
</style>
<form name="form" novalidate>
<input type="text" ng-model="id">
<input type="button" value="Test" ng-click='doTest()'>
</form>
</body>
<script src="bower_components/angular/angular.js">
</script>
<html>
javascript:
var app = angular.module('app',[]);
app.factory('dataService',function($timeout){
var service={};
service.persons=[{id:1,name:'Jim'},{id:2,name:'Tom'},{id:3,name:'Agile'}];
service.getName=function(id,callback,errorCallback){
$timeout(function(){
for(var i in service.persons){
var person = service.persons[i];
if(person.id==id){
callback(person.name);
return;
}
}
errorCallback('can not find person by id: '+id);
},2000);
};
return service;
});
app.controller('ctrl',function($scope,$q,dataService){
$scope.id='';
function getName(id){
return $q(function(r,j){
dataService.getName(id,function(data){
r(data);
},function(data){
j(data);
});
});
};
$scope.doTest=function(){
var id = $scope.id;
getName(id).then(function(data){
alert('Name is '+data);
},function(data){
alert('failed: '+data);
});
}
console.log('done');
});
then方法接受2个function作为参数,第一个是resolve,第二个是reject。其实把ajax请求改写成promise并不能体现$q的威力。
改写后代码跟原来的代码没有太大的差别。
no promise:
getName(id,function(){},function());
promise:
getName(id).then(function(){},function(){});
promise形式只是把2个回掉提到了then方法里,只是看起来更同步了一点而已。
其实$http服务本身就是通过$q来实现的promise,所以当你使用$q来做ajax的时候已经非常promise了。
$q最大的好处我觉得在于$q.all方法,它可以等待多个promise完成之后在执行相应的代码,下回分享。