什么是Promise
Javascript中異步的實現(xiàn)方式有很多,延時函數(shù)、回調(diào)函數(shù)、以及es6新增的生成器函數(shù),其中Promise也是實現(xiàn)異步的方式之一。
關(guān)于javascript中的異步實現(xiàn)方式的詳解以及區(qū)別,后期會更新博客,敬請期待,此處不再贅述。
$q服務(wù)
簡言之$q服務(wù)是AngularJS中自己封裝實現(xiàn)的一種Promise實現(xiàn)。先介紹一下$q常用的幾個方法:
- defer() 創(chuàng)建一個deferred對象,這個對象可以執(zhí)行幾個常用的方法,比如resolve,reject,notify等
- all() 傳入Promise的數(shù)組,批量執(zhí)行,返回一個promise對象
- when() 傳入一個不確定的參數(shù),如果符合Promise標(biāo)準(zhǔn),就返回一個promise對象。
需要注意的是在Promise中,定義了三種狀態(tài):等待狀態(tài),完成狀態(tài),拒絕狀態(tài)。
關(guān)于狀態(tài)有兩個規(guī)定:
1.狀態(tài)的變更是不可逆的
2.等待狀態(tài)可以變成完成或者拒絕
defer()方法
在$q中,可以使用resolve方法,變成完成狀態(tài);使用reject方法,變成拒絕狀態(tài)。
其中defer()用于創(chuàng)建一個deferred對象,defer.promise用于返回一個promise對象,來定義then方法。then中有三個參數(shù),分別是成功回調(diào)、失敗回調(diào)、狀態(tài)變更回調(diào)。
下面看一個公司項目遇到的實例:
'use strict';
angular.module('app')
.controller('positionCtrl',['$scope','$state','$q','$stateParams','$http',function ($scope,$state,$q,$stateParams,$http) {
var vm = this;
vm.position;
vm.company;
vm.isLogin = false;
function getPosition() {
var def = $q.defer();
$http.get('/data/position.json?id = ' + $stateParams.id)
.then(function (resp) {
vm.position = resp.data;
// console.log(resp.data);
// console.log(vm.position);
def.resolve(resp);
}).catch(function () {
def.reject(err);
});
return def.promise;
};
function getCompany(id) {
$http.get('data/company.json?id='+id)
.then(function (resp) {
vm.company = resp.data;
// console.log(vm.company);
})
.catch(function (err) {
console.log(err);
});
};
getPosition().then(function (obj) {
getCompany(obj.companyId);
});
}]);
上述代碼業(yè)務(wù)邏輯其實很簡單,首先要獲取公司職位vm.position,根據(jù)職位信息中的companyId來獲取公司vm.company。
在第一個函數(shù)中g(shù)etPosition中,首先調(diào)用$q.defer()方法得到一個deferred對象。 return def.promise;語句很顯然使得函數(shù)getPosition返回一個Promise對象,這樣在調(diào)用 getPosition()函數(shù)之后可以直接使用.then()方法。
getPosition().then(function (obj) {
getCompany(obj.companyId);
});
這樣就把兩個函數(shù)的同步執(zhí)行,變成了異步執(zhí)行。
all()方法
這個all()方法,可以把多個primise的數(shù)組合并成一個。當(dāng)所有的promise執(zhí)行成功后,會執(zhí)行后面的回調(diào)?;卣{(diào)中的參數(shù),是每個promise執(zhí)行的結(jié)果。
當(dāng)批量的執(zhí)行某些方法時,就可以使用這個方法。
var funcA = function(){
var def = $q.defer();
console.log("funcA");
//some code
return def.promise;
}
var funcB = function(){
var def = $q.defer();
console.log("funcA");
//some code
return def.promise;
}
$q.all([funcA(),funcB()])
.then(function(result){
console.log(result);
});