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 拾碎[三] 使用className属性
Oct 16 Javascript
javascript中全局对象的isNaN()方法使用介绍
Dec 19 Javascript
JS基于cookie实现来宾统计记录访客信息的方法
Aug 04 Javascript
jquery+ajax请求且带返回值的代码
Aug 12 Javascript
JS动态加载脚本并执行回调操作
Aug 24 Javascript
BootStrap Table对前台页面表格的支持实例讲解
Dec 22 Javascript
使用Promise链式调用解决多个异步回调的问题
Jan 15 Javascript
JavaScript实现类似淘宝的购物车效果
Mar 16 Javascript
JavaScript表单即时验证 验证不成功不能提交
Aug 31 Javascript
7个好用的JavaScript技巧分享(译)
May 07 Javascript
解决layui调用自定义方法提示未定义的问题
Sep 14 Javascript
jQuery实现的图片点击放大缩小功能案例
Jan 02 jQuery
利用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
[FAQ]PHP中的一些常识:类篇
2006/10/09 PHP
php下尝试使用GraphicsMagick的缩略图功能
2011/01/01 PHP
php抓取页面的几种方法详解
2013/06/17 PHP
Node.js开发指南中的简单实例(mysql版)
2013/09/17 Javascript
JS替换文本域内的回车示例
2014/02/18 Javascript
Jquery焦点与失去焦点示例应用
2014/06/10 Javascript
js实现的Easy Tabs选项卡用法实例
2015/09/06 Javascript
Bootstrap每天必学之进度条
2015/11/30 Javascript
seajs学习教程之基础篇
2016/10/20 Javascript
浅谈EasyUI常用控件的禁用方法
2016/11/09 Javascript
Javascript之面向对象--接口
2016/12/02 Javascript
jQuery动态生成表格及右键菜单功能示例
2017/01/13 Javascript
canvas 绘制圆形时钟
2017/02/22 Javascript
JS判断非空至少输入两个字符的简单实现方法
2017/06/23 Javascript
javaScript实现复选框全选反选事件详解
2020/11/20 Javascript
vue中keep-alive的用法及问题描述
2018/05/15 Javascript
vue滚动tab跟随切换效果
2020/06/29 Javascript
基于layui实现高级搜索(筛选)功能
2019/07/26 Javascript
js实现百度登录窗口拖拽效果
2020/03/19 Javascript
JavaScript面向对象核心知识与概念归纳整理
2020/05/09 Javascript
python在windows下实现ping操作并接收返回信息的方法
2015/03/20 Python
Python基于百度AI实现OCR文字识别
2020/04/02 Python
基于HTML5 FileSystem API的使用介绍
2013/04/24 HTML / CSS
HTML5、Select下拉框右边加图标的实现代码(增进用户体验)
2017/10/16 HTML / CSS
爱尔兰灯和灯具网上商店:Lights.ie
2018/03/26 全球购物
什么是反射?如何实现反射?
2016/07/25 面试题
大学生个人事迹材料
2014/01/21 职场文书
2014庆六一活动方案
2014/03/02 职场文书
调研汇报材料范文
2014/08/17 职场文书
2015年初中元旦晚会活动总结
2014/11/28 职场文书
慈善募捐倡议书
2015/04/27 职场文书
Java集成swagger文档组件
2021/06/28 Java/Android
Windows下用Nginx配置https服务器及反向代理的问题
2021/09/25 Servers
SQL优化老出错,那是你没弄明白MySQL解释计划用法
2021/11/27 MySQL
python lambda 表达式形式分析
2022/04/03 Python
MySQL表字段数量限制及行大小限制详情
2022/07/23 MySQL