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 相关文章推荐
javascript instanceof 与typeof使用说明
Jan 11 Javascript
javascript encodeURI和encodeURIComponent的比较
Apr 03 Javascript
jQuery 工具函数学习资料
Apr 29 Javascript
需灵活掌握的Bootstrap预定义排版类 你精通吗?
Jun 20 Javascript
Javascript中浏览器窗口的基本操作总结
Aug 18 Javascript
js判断浏览器是否支持严格模式的方法
Oct 04 Javascript
基于jQuery实现火焰灯效果导航菜单
Jan 04 Javascript
JS复制对应id的内容到粘贴板(Ctrl+C效果)
Jan 23 Javascript
canvas实现图片根据滑块放大缩小效果
Feb 24 Javascript
利用jQuery实现一个简单的表格上下翻页效果
Mar 14 Javascript
微信小程序引入Vant组件库过程解析
Aug 06 Javascript
JS array数组检测方式解析
May 19 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 htmlspecialchars()与shtmlspecialchars()函数的深入分析
2013/06/05 PHP
学习php设计模式 php实现策略模式(strategy)
2015/12/07 PHP
php中让人头疼的浮点数运算分析
2016/10/10 PHP
php命令行写shell实例详解
2018/07/19 PHP
laravel 时间格式转时间戳的例子
2019/10/11 PHP
JS 强制设为首页的代码
2009/01/31 Javascript
Javascript 学习书 推荐
2009/06/13 Javascript
Prototype Selector对象学习
2009/07/23 Javascript
Javascript实现DIV滚动自动滚动到底部的代码
2012/03/01 Javascript
深入理解JavaScript 闭包究竟是什么
2013/04/12 Javascript
利用cookie记住背景颜色示例代码
2013/11/04 Javascript
JS获取时间的相关函数及时间戳与时间日期之间的转换
2016/02/04 Javascript
快速移动鼠标触发问题及解决方法(ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave)
2016/08/29 Javascript
vue 实现类似淘宝星级评分的示例
2018/03/01 Javascript
JS实现为动态创建的元素添加事件操作示例
2018/03/17 Javascript
angular 实时监听input框value值的变化触发函数方法
2018/08/31 Javascript
微信小程序获取用户信息及手机号(后端TP5.0)
2019/09/12 Javascript
JQuery获得内容和属性方法解析
2020/05/30 jQuery
Python实现批量把SVG格式转成png、pdf格式的代码分享
2014/08/21 Python
python通过urllib2获取带有中文参数url内容的方法
2015/03/13 Python
python实现图像检索的三种(直方图/OpenCV/哈希法)
2019/08/08 Python
python多线程高级锁condition简单用法示例
2019/11/07 Python
Python项目跨域问题解决方案
2020/06/22 Python
Pytorch框架实现mnist手写库识别(与tensorflow对比)
2020/07/20 Python
Python通过Schema实现数据验证方式
2020/11/12 Python
最新Python idle下载、安装与使用教程图文详解
2020/11/28 Python
HTML5中Localstorage的使用教程
2015/07/09 HTML / CSS
网站性能延迟加载图像的五种技巧(小结)
2020/08/13 HTML / CSS
巴西电子产品购物网站:Saldão da Informática
2018/01/09 全球购物
德国滑雪和户外用品网上商店:XSPO
2019/10/30 全球购物
C#面试常见问题
2013/02/25 面试题
医学生自荐信
2013/12/03 职场文书
党课学习思想汇报
2014/01/02 职场文书
市场部管理制度
2014/02/02 职场文书
2015年财务科工作总结范文
2015/05/13 职场文书
SQL Server中T-SQL标识符介绍与无排序生成序号的方法
2022/05/25 SQL Server