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 相关文章推荐
表单提交时自动复制内容到剪贴板的js代码
Mar 16 Javascript
用Javascript评估用户输入密码的强度实现代码
Nov 30 Javascript
jsonp原理及使用
Oct 28 Javascript
js获取select标签的值且兼容IE与firefox
Dec 30 Javascript
Js保留小数点的4种效果实现代码分享
Apr 12 Javascript
javascript解析json数据的3种方式
May 08 Javascript
基于Jquery+Ajax+Json实现分页显示附效果图
Jul 30 Javascript
jQuery on()方法使用技巧详解
Apr 16 Javascript
JS组件Bootstrap dropdown组件扩展hover事件
Apr 17 Javascript
JS中的数组方法笔记整理
Jul 26 Javascript
js获取隐藏元素的宽高
Feb 24 Javascript
react-router-dom 嵌套路由的实现
May 02 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 字符串正则替换函数preg_replace使用说明
2011/07/15 PHP
解析PHP 5.5 新特性
2013/07/02 PHP
PHP内存使用情况如何获取
2015/10/10 PHP
Laravel学习笔记之Artisan命令生成自定义模板的方法
2018/11/22 PHP
DWZ table的原生分页浅谈
2013/03/01 Javascript
javascript遍历控件实例详细解析
2014/01/10 Javascript
jquery实现图片放大镜功能
2015/11/23 Javascript
js控制TR的显示隐藏
2016/03/04 Javascript
纯css下拉菜单 无需js
2016/08/15 Javascript
微信小程序 购物车简单实例
2016/10/24 Javascript
基于JavaScript实现带缩略图的轮播效果
2017/01/12 Javascript
使用contextMenu插件实现Bootstrap table弹出右键菜单
2017/02/20 Javascript
Mongoose经常返回e11000 error的原因分析
2017/03/29 Javascript
关于Vue Webpack2单元测试示例详解
2017/08/14 Javascript
如何把vuejs打包出来的文件整合到springboot里
2018/07/26 Javascript
在Python的列表中利用remove()方法删除元素的教程
2015/05/21 Python
tensorflow使用神经网络实现mnist分类
2018/09/08 Python
Django模板Templates使用方法详解
2019/07/19 Python
python多线程+代理池爬取天天基金网、股票数据过程解析
2019/08/13 Python
Python Django 页面上展示固定的页码数实现代码
2019/08/21 Python
python爬虫爬取笔趣网小说网站过程图解
2019/11/18 Python
django修改models重建数据库的操作
2020/03/31 Python
python随机模块random的22种函数(小结)
2020/05/15 Python
Django 构建模板form表单的两种方法
2020/06/14 Python
HTML5 虚拟键盘出现挡住输入框的解决办法
2017/02/14 HTML / CSS
英国优质家居用品网上品牌:URBANARA
2018/06/01 全球购物
西班牙土拨鼠床垫公司,感觉在云端:Marmota
2019/03/18 全球购物
美国在线购买内衣网站:HerRoom
2020/02/22 全球购物
TCP/IP中的TCP和IP分别承担什么责任
2012/04/21 面试题
护士的岗位职责
2013/12/04 职场文书
2015年度招聘工作总结
2015/05/28 职场文书
六一活动主持词
2015/06/30 职场文书
Redis如何一键部署脚本
2021/04/12 Redis
MySQL创建管理KEY分区
2022/04/13 MySQL
Golang Elasticsearches 批量修改查询及发送MQ
2022/04/19 Golang
关于windows server 2012 DC 环境 重启后蓝屏代码:0xc00002e2的问题
2022/05/25 Servers