Angular异步变同步处理方法


Posted in Javascript onAugust 13, 2018

1. 背景

在前端项目中,经常会遇到页面有多个接口,后一个接口参数需要从前一个接口的返回数据中获取,这就存在接口必须按顺序一个一个执行。而Angular提供的Http服务请求接口都是异步请求,因此通常情况下会写成如下的代码:

funA(arg1,arg2,function(){
 funcB(arg1,arg2,function(){
  funcC(arg1,arg2,function(){
    xxxx....
  })
 }) 
});

这不仅造成页面代码混乱不易维护,也让开发者无法追踪代码的运行。本身嵌套就已经不容易理解,加上不知何时才能触发回调,这就相当于雪上加霜。

2. Promise

针对这中现象,Angular推出了Promise规范,它可以帮助开发者将异步变成同步,是一种对执行结果不确定的一种预先定义。例如以下代码中,当getData方法内的对象成功执行,就会调用success方法,如果失败,就会调用error方法。另外promise除了then方法之外,还有catch()与finally()方法。

defer. getData()
.then( funcSuccess (){}, funcError (){} )
.catch( function(){})
.finally( function(){});

Finally()方法一般用来处理不管promise是返回成功还是失败,都会执行的操作。例如ionic中的上拉加载,当获取数据后不管成功或者失败,都要广播结束这次上拉操作,便可将这个操作写在finally()方法中。

3. $q服务

q服务是AngularJs中自己封装实现的一种Promise实现,一般有如下三个常用方法:

defer() :创建一个deferred对象,这个对象可以执行几个常用的方法,比如resolve,reject,notify等;

all() :传入Promise的数组,批量执行,返回一个Promise对象;

when() :传入一个不确定的参数,如果符合Promise标准,就返回一个Promise对象。

3.1. defer() 方法

在$q服务中,用defer()方法创建一个deferred对象,然后这个对象可以调用resolve方法定义成功状态,使用reject方法定义失败状态,并且可以在这些方法中传递参数,一般接口返回的数据都是用这些方法传递出去。最后通过deferred对象 .promise来返回一个promise对象,来定义then方法。then方法中有三个参数,分别是成功回调、失败回调、状态变更回调。

定义方法:

function funA(num){
 var defer = $q.defer();
 if(num<5){
 defer.resolve('funA success');
 }else{
 defer.reject('funA error');
 }
 return defer.promise;
}

方法调用(返回成功):

funA(3).then(function(success){
 console.log(success);
},function(err){
 console.log(err);
})

结果:

Angular异步变同步处理方法

方法调用(返回失败):

funA(8).then(function(success){
 console.log(success);
},function(err){
 console.log(err);
})

结果:

Angular异步变同步处理方法

3.2. 链式调用

了解了defer()方法与then()方法,接下来就能解决多个接口嵌套调用的问题了。

一般处理多个接口需要嵌套执行时,可采用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);
}).then(function(success){
 console.log(success);
},function(err){
 console.log(err);
});

结果:

Angular异步变同步处理方法

上述方法调用中,then()方法中只写了成功参数的方法,如果其中一个方法调用返回失败,则该方法后边的方法都不会再执行,也就是只有前一个方法调用成功,才能调用后边的方法。如下为其中一个方法失败的示例,funB方法调用返回失败,则不会再执行funC,而错误的信息会在最后捕捉错误信息的参数方法中获取。

方法调用:

funA(3).then(function(success){
 console.log(success);
 return funB(8);
}).then(function(success){
 console.log(success);
 return funC(3);
}).then(function(success){
 console.log(success);
},function(err){
 console.log(err); //打印funB()的错误信息
});

结果:

Angular异步变同步处理方法

如果在某些场景中,等前一个方法调用完毕,而不管这个方法是否调用成功,都要继续调用后边的方法,则需要在then()方法中增加错误回调并return 下一个执行的promise。如下:

funA(3).then(function(success){
 console.log(success);
 return funB(8);
},function(err){
 console.log(err);
 return funB(8);
}).then(function(success){
 console.log(success);
 return funC(3);
},function(err){
 console.log(err);
 return funC(3);
}).then(function(success){
 console.log(success);
},function(err){
 console.log(err);
});

结果:

Angular异步变同步处理方法

3.3. all() 方法

all()方法可以把多个promise的数组合并成一个。当所有的promise执行成功后,会执行后面的回调,回调中的参数,是每个promise执行的结果。

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;
}

方法调用:

$q.all([
 funA(3), 
 funB(3)
 ])
.then(function(success){
 console.log(success);
},function(err){
 console.log(err);
})

结果:

Angular异步变同步处理方法

all() 方法中的参数可以是上面的数组形式,也可以是json格式。相应的,如果参数是数组格式,那么返回的数据格式也是数组格式;如果参数是json格式,那么返回的数据格式也是json格式。json参数示例如下:

$q.all(
 {
 funA:DeferService.funA(3),
 funB:DeferService.funB(3)
 })
.then(function(success){
 console.log(success);
},function(err){
 console.log(err);
})

结果:

Angular异步变同步处理方法

上面两个示例展示的都是获取数据成功的情况。而当all()方法的参数中存在一个promise失败,则整个任务都失败,返回的数据也只会返回该失败参数的失败信息。

方法调用:

$q.all(
 {
 funA:DeferService.funA(8), //调用失败
 //正常情况下是调用成功,但由于funA调用失败,固该方法也是失败
 funB:DeferService.funB(3) 
})
.then(function(success){
 console.log(success);
},function(err){
 console.log(err);
})

结果:

Angular异步变同步处理方法

3.4. when() 方法

when()方法中的参数可以是一个值,也可以是一个promise,这个方法是把传入的参数处理包装成一个promise。这个方法一般在你不确定所处理的对象或者调用的方法是不是一个promise时使用。

例如在下面的例子中,val=10,并不是一个promise,但是经过when()方法包装之后,可以通过.then()方法去调用,像处理平常的promise一样。

var val=10;
$q.when(val)
 .then(function(success){
 console.log(success);
 },function(err){
 console.log(err);
 });

结果:

Angular异步变同步处理方法

以上这篇Angular异步变同步处理方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
用正则表达式 动态创建/增加css style script 兼容IE firefox
Mar 10 Javascript
Jquery 高亮显示文本中重要的关键字
Dec 24 Javascript
jquery实现控制表格行高亮实例
Jun 05 Javascript
jquery live()调用不存在的解决方法
Feb 26 Javascript
javascript禁止访客复制网页内容的实现代码
Aug 05 Javascript
javascript实现计时器的简单方法
Feb 21 Javascript
jQuery自适应轮播图插件Swiper用法示例
Aug 24 Javascript
JavaScript仿微博发布信息案例
Nov 16 Javascript
javascript操作cookie
Jan 17 Javascript
JS html事件冒泡和事件捕获操作示例
May 01 Javascript
使vue实现jQuery调用的两种方法
May 12 jQuery
解决vue init webpack 下载依赖卡住不动的问题
Nov 09 Javascript
利用JS实现一个同Excel表现的智能填充算法
Aug 13 #Javascript
Vue自定义弹窗指令的实现代码
Aug 13 #Javascript
深入Vue-Router路由嵌套理解
Aug 13 #Javascript
AngularJS与后端php的数据交互方法
Aug 13 #Javascript
Vue Promise的axios请求封装详解
Aug 13 #Javascript
Angular6封装http请求的步骤详解
Aug 13 #Javascript
解决angularjs中同步执行http请求的方法
Aug 13 #Javascript
You might like
PHP - Html Transfer Code
2006/10/09 PHP
php截取utf-8中文字符串乱码的解决方法
2010/03/29 PHP
php中自定义函数dump查看数组信息类似var_dump
2014/01/27 PHP
thinkphp框架下实现登录、注册、找回密码功能
2016/04/06 PHP
浅谈PHP的反射API
2017/02/26 PHP
thinkphp5实现微信扫码支付
2019/12/23 PHP
基于jQuery实现表格数据的动态添加与统计的代码
2011/01/31 Javascript
玩转jQuery按钮 请告诉我你最喜欢哪些?
2012/01/08 Javascript
javascript数据结构与算法之检索算法
2015/04/04 Javascript
JavaScript实现表格点击排序的方法
2015/05/11 Javascript
如何屏蔽防止别的网站嵌入框架代码
2015/08/24 Javascript
小心!AngularJS结合RequireJS做文件合并压缩的那些坑
2016/01/09 Javascript
详解Javascript中的Object对象
2016/02/28 Javascript
JavaScript 数组some()和filter()的用法及区别
2016/05/20 Javascript
JQuery.validationEngine表单验证插件(推荐)
2016/12/10 Javascript
Angular的事件和表单详解
2016/12/26 Javascript
如何快速上手Vuex
2017/02/14 Javascript
深入理解React中何时使用箭头函数
2017/08/23 Javascript
jQuery动态添加元素无法触发绑定事件的解决方法分析
2018/01/02 jQuery
vue安装和使用scss及sass与scss的区别详解
2018/10/15 Javascript
[05:06]TI4西雅图DOTA2前线报道 海涛密探LGD训练
2014/07/09 DOTA
pymssql ntext字段调用问题解决方法
2008/12/17 Python
Python文件操作基本流程代码实例
2017/12/11 Python
Flask框架各种常见装饰器示例
2018/07/17 Python
解决python 上传图片限制格式问题
2019/10/30 Python
日本最新流行服饰网购:Nissen
2016/07/24 全球购物
美国在线工具商店:Acme Tools
2018/06/26 全球购物
阿联酋航空丹麦官方网站:Emirates DK
2019/08/25 全球购物
日期和时间问题
2015/01/04 面试题
如何将一个描述日期或日期/时间的字符串转换为一个Date对象
2015/10/13 面试题
英语自我评价范文
2014/01/24 职场文书
活动总结范文
2014/08/30 职场文书
2015年政风行风工作总结
2015/04/21 职场文书
您对思维方式了解多少?
2019/12/09 职场文书
Python Numpy之linspace用法说明
2021/04/17 Python
浅谈MySQL之select优化方案
2021/08/07 MySQL