文章参考
http://www.aspzz.cn/article/61638.htm
http://www.cnblogs.com/xing901022/p/4928147.html
Promise
Promise是一种模式,以同步操作的流程形式来操作异步事件,避免了层层嵌套,可以链式操作异步事件。
我们知道,在编写javascript异步代码时,callback是最最简单的机制,可是用这种机制的话必须牺牲控制流、异常处理和函数语义化为代价,甚至会让我们掉进出现callback大坑,而promise解决了这个问题。
ES6中Promise、angularJS内置的AngularJS内置Q,以及when采用的都是Promises/A规范,如下:
每个任务都有三种状态:未完成(pending)、完成(fulfilled)、失败(rejected)。
1.pending状态:可以过渡到履行或拒绝状态。
2.fulfilled状态:不能变为其他任何状态,而且状态不能改变,必须有value值。
3.rejected状态:不能变为其他任何状态,而且状态不能改变,必须有reason。
状态的转移是一次性的,状态一旦变成fulfilled(已完成)或者failed(失败/拒绝),就不能再变了。
$q服务
q服务是AngularJS中自己封装实现的一种Promise实现,相对与Kris Kwal's Q要轻量级的多。
先介绍一下$q常用的几个方法:
defer() 创建一个deferred对象,这个对象可以执行几个常用的方法,比如resolve,reject,notify等
all() 传入Promise的数组,批量执行,返回一个promise对象
when() 传入一个不确定的参数,如果符合Promise标准,就返回一个promise对象。
案例
function okToGreet(name){
return name === 'Robin Hood';
}
function asyncGreet(name) {
var deferred = $q.defer();
setTimeout(function() {
// 因为这个异步函数fn在未来的异步执行,我们把代码包装到 $apply 调用中,一边正确的观察到 model 的改变
$scope.$apply(function() {
//执行promise.then的第三个参数(notifyCallback)方法
deferred.notify('About to greet ' + name + '.');
if (okToGreet(name)) {
//执行promise.then的第一个参数(successCallback)方法
deferred.resolve('Hello,' + name + '!');
} else {
//执行promise.then的第二个参数(errorCallback)方法
deferred.reject('Greeting ' + name + ' is not allowed.');
}
});
},1000);
return deferred.promise;
}
var promise = asyncGreet('Robin Hood');
promise.then(function(greeting) {
alert('Success: ' + greeting);
},function(reason) {
alert('Failed: ' + reason);
},function(update) {
alert('Got notification: ' + update);
});
Promise API
当创建 deferred 实例时会创建一个新的 promise 对象,并可以通过 deferred.promise 得到该引用。
promise 对象的目的是在 deferred 任务完成时,允许感兴趣的部分取得其执行结果。
promise 对象的方法
then(successCallback,errorCallback,notifyCallback):参数为不同消息下的不同回调函数,defer发送不同的消息执行不同的回调函数,消息作为这些回调函数的参数传递。返回值为回一个promise对象为支持链式调用而存在。当第一个defer对象发送消息后,后面的promise对应的defer对象也会发送消息,但是发送的消息不一样,不管第一个defer对象发送的是reject还是resolve,第二个及其以后的都是发送的resolve,消息是可传递的。
catch(errorCallback):then(null,errorCallback)的缩写。
finally(callback):相当于then(callback,callback)的缩写,这个finally中的方法不接受参数,却可以将defer发送的消息和消息类型成功传递到下一个then中。
下面是自己工作中写的例子——两个异步请求,如何按照顺序执行(异步请求同步处理)
/**
* 进入页面的控制器 controller
* */
angular.module("hkApp").controller("salesGoodsTop10Controller",["$scope","$state",'salesGoodsTop10Service',function ($scope,$state,salesGoodsTop10Service) {
//第一步,获取前十的商品list
var promise = salesGoodsTop10Service.getSalesGoodsStatisticsList();
promise.then(function(returnData){
$scope.lists = returnData.data;
//第二步,获取商品的总数量,返回的是promise对象,作为第二个then的执行方法
return salesGoodsTop10Service.getGatherTotal();
}).then(function(returnData){
$scope.gatherTotal = returnData.data;
});
$scope.goBack = function(){
window.history.back();
};
}]);
/**
* 向服务器发送请求的服务 service
* */
angular.module("hkApp").factory("salesGoodsTop10Service",["$http","$q",function($http,$q){
/**
* 获取商品前10的商品
* */
var getSalesGoodsStatisticsList = function (){
var deferred = $q.defer();
var url = "/index.php/Admin/GatherGoods/gatherGoodsTop.html";
var params = {
"top":5
};
$http.post(url,params)
.success(function(response,status,headers,config){
if(response.status == 1){
deferred.resolve(response);
}
});
return deferred.promise;
};
/**
* 获取销售商品总数
* */
var getGatherTotal = function (){
var deferred = $q.defer();
var url = "/index.php/Admin/GatherGoods/gatherTotal.html";
$http.post(url)
.success(function(response,config){
if(response.status == 1){
deferred.resolve(response);
}
});
return deferred.promise;
};
var resultJson = {
"getSalesGoodsStatisticsList":getSalesGoodsStatisticsList,"getGatherTotal":getGatherTotal
};
return resultJson;
}]);
