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); })
结果:
方法调用(返回失败):
funA(8).then(function(success){ console.log(success); },function(err){ console.log(err); })
结果:
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); });
结果:
上述方法调用中,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()的错误信息 });
结果:
如果在某些场景中,等前一个方法调用完毕,而不管这个方法是否调用成功,都要继续调用后边的方法,则需要在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); });
结果:
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); })
结果:
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); })
结果:
上面两个示例展示的都是获取数据成功的情况。而当all()方法的参数中存在一个promise失败,则整个任务都失败,返回的数据也只会返回该失败参数的失败信息。
方法调用:
$q.all( { funA:DeferService.funA(8), //调用失败 //正常情况下是调用成功,但由于funA调用失败,固该方法也是失败 funB:DeferService.funB(3) }) .then(function(success){ console.log(success); },function(err){ console.log(err); })
结果:
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异步变同步处理方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]