AngularJS调接口异步变同步处理
1.背景
在前端项目中,经常会遇到页面有多个接口,后一个接口参数需要从前一个接口的返回数据中获取,这就存在接口必须按顺序一个一个执行。而Angular提供的Http服务请求接口都是异步请求,因此通常情况下会写成如下的代码:
funA(arg1,arg2,function(){
funcB(arg1,arg2,function(){
funcC(arg1,arg2,function(){
xxxx....
})
})
});
这种方式会造成页面代码混乱不易维护
应用场景:如果有一个需求需要先获取用户信息(如getUser()),之后获取用户权限(如getPermission())。假设两个方法都是异步的,那在直接调用的时候:
getUser();
getPermission();
这样有可能出现在得到用户信息前就调用getPermission()方法,这样逻辑就有问题就会出错。
2.Promise
针对这种现象,Angular推出了Promise规范,它可以帮助开发者将异步变成同步,避免了层层嵌套的回调函数。Promise 就像一个中介,它承诺会将一个可信任的异步结果返回。首先 Promise 和异步接口签订一个协议,成功时,调用resolve函数通知Promise,异常时,调用reject通知 Promise。
3.$q服务
在angularjs中创建promise,可以使用内置的q服务,q服务是AngularJs中自己封装实现的一种Promise实现,一般有如下三个常用方法:
defer() :创建一个deferred对象,这个对象可以执行几个常用的方法,比如resolve,reject,notify等;
all() :传入Promise的数组,批量执行,返回一个Promise对象;
when() :传入一个不确定的参数,如果符合Promise标准,就返回一个Promise对象。
3.1 defer()方法
在$q服务中,用defer()方法创建一个deferred对象。
var defer = $q.defer();
然后这个对象可以调用resolve方法定义成功状态,使用reject方法定义失败状态,并且可以在这些方法中传递参数,一般接口返回的数据都是用这些方法传递出去。
最后通过deferred对象 .promise来返回一个promise对象。
return defer.promise;
3.2 链式调用
一般处理多个接口需要嵌套执行时,可采用angular的链式调用,即:
FunA.then().then().then();
在then方法中return 要调用的下一个接口。如下funA、funB、funC都是返回了promise对象的方法,如果执行顺序为funA、funB、funC,则可用链式调用。
function funA(num){
var defer = $q.defer();
if(num<5){
defer.resolve('funA success');
}else{
defer.reject('funA error');
}
return defer.promise;
}
function funB(num){
var defer = $q.defer();
if(num<5){
defer.resolve('funB success');
}else{
defer.reject('funB error');
}
return defer.promise;
}
function funC(num){
var defer = $q.defer();
if(num<5){
defer.resolve('funC success');
}else{
defer.reject('funC error');
}
return defer.promise;
}
方法调用:
funA(3).then(function(success){
console.log(success);
return funB(3);
}).then(function(success){
console.log(success);
return funC(3);
});