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定义函数的方法
Dec 06 Javascript
你必须知道的JavaScript 中字符串连接的性能的一些问题
May 07 Javascript
jquery右下角弹出提示框示例代码
Oct 08 Javascript
JavaScript 异常处理 详解
Feb 06 Javascript
Javascript中作用域的详细介绍
Oct 06 Javascript
node.js平台下利用cookie实现记住密码登陆(Express+Ejs+Mysql)
Apr 26 Javascript
webpack打包后直接访问页面图片路径错误的解决方法
Jun 17 Javascript
VueJS组件之间通过props交互及验证的方式
Sep 04 Javascript
vue2实现数据请求显示loading图
Nov 28 Javascript
vue使用codemirror的两种用法
Aug 27 Javascript
vue resource发送请求的几种方式
Sep 30 Javascript
vue路由传参的基本实现方式小结【三种方式】
Feb 05 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&amp;java(二)
2006/10/09 PHP
PHP5中的时间相差8小时的解决办法
2008/03/28 PHP
php封装的page分页类完整实例
2016/10/18 PHP
ThinkPHP5.0框架实现切换数据库的方法分析
2019/10/30 PHP
javascript 原型模式实现OOP的再研究
2009/04/09 Javascript
关于javascript DOM事件模型的两件事
2010/07/22 Javascript
基于jquery的大众点评,分类导航实现代码
2011/08/23 Javascript
Jquery 表格合并的问题分享
2011/09/17 Javascript
关于JavaScript对象的动态选择及遍历对象
2014/03/10 Javascript
IE6-IE9中tbody的innerHTML不能赋值的解决方法
2014/06/05 Javascript
JavaScript编写推箱子游戏
2015/07/07 Javascript
jquery  实现轮播图详解及实例代码
2016/10/12 Javascript
Jquery Easyui分割按钮组件SplitButton使用详解(17)
2016/12/18 Javascript
JavaScript数组去重的6个方法
2017/01/21 Javascript
Javascript中for循环语句的几种写法总结对比
2017/01/23 Javascript
基于JS实现移动端左滑删除功能
2017/07/28 Javascript
JavaSctit 利用FileReader和滤镜上传图片预览功能
2017/09/05 Javascript
Node.js爬取豆瓣数据实例分析
2018/03/05 Javascript
boostrap模态框二次弹出清空原有内容的方法
2018/08/10 Javascript
解决angularJS中input标签的ng-change事件无效问题
2018/09/13 Javascript
解决vue.js中settimeout遇到的问题(时间参数短效果不稳定)
2020/07/21 Javascript
使用PyInstaller将Python程序文件转换为可执行程序文件
2016/07/08 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
2017/11/09 Python
python制作mysql数据迁移脚本
2019/01/01 Python
python 应用之Pycharm 新建模板默认添加编码格式-作者-时间等信息【推荐】
2019/06/17 Python
Python +Selenium解决图片验证码登录或注册问题(推荐)
2020/02/09 Python
在python中利用dict转json按输入顺序输出内容方式
2020/02/27 Python
python 安装库几种方法之cmd,anaconda,pycharm详解
2020/04/08 Python
使用Keras预训练模型ResNet50进行图像分类方式
2020/05/23 Python
机关办公室岗位职责
2014/04/16 职场文书
分公司经理任命书
2014/06/05 职场文书
低碳环保口号
2014/06/12 职场文书
信用卡工资证明格式
2014/09/13 职场文书
幼儿园小班家长评语
2014/12/30 职场文书
谢师宴家长答谢词
2015/09/30 职场文书
CSS3实现列表无限滚动/轮播效果
2021/06/23 HTML / CSS