为了账号安全,请及时绑定邮箱和手机立即绑定

关于js里promise的自调用疑惑。

关于js里promise的自调用疑惑。

小怪兽爱吃肉 2019-04-09 20:25:44
代码场景大致如下。要从redis里获取一个结果集列表,获取的时候先判断是否存在缓存,如果没的话先设置缓存再调用。先贴下函数声明的代码。exports.totalRank=function(){vartrDeferred=Q.defer();Q.all([RedisDB.getDailyRankList(),RedisDB.getWeeklyRankList(),RedisDB.getMonthlyRankList()]).done(function(result){if(cacheExistsChecker(result)){varreturnResult={dailyRank:JSON.parse(result[0])[0].rank,weeklyRank:JSON.parse(result[1])[0].rank,monthlRank:JSON.parse(result[2])[0].rank,}trDeferred.resolve(returnResult);}else{CacheAction.setRanksLists().then(function(){RankAction.totalRank().then(function(result){trDeferred.resolve(result);})});}})returntrDeferred.promise;}调用该函数的代码如下:RankAction.totalRank().then(function(result){console.log(result);}).fail(function(err){console.log(err);});调用该方法时候,缓存不存在,所以肯定是进入了else的流程。现在疑惑就是:重点关注函数声明那段代码,else里面的RankAction.totalRank().then()里面的trDeferred,该对象是第一次调用就return了的promise对象,还是第一次判断缓存不存在,然后再重新调用totalRank时候重新var的trDeferred?个人的理解是第一次的trdeferred。因为如果这里不用RankAction.totalRank().then(xxxx),而是直接RankAction.totalRank(),则不返回结果。求分析解惑一下。
查看完整描述

2 回答

?
慕的地10843

TA贡献1785条经验 获得超8个赞

既然已经用了all,就没必要再构造defer绕一圈了
returnall([getA(),getB(),getC()).then(function(result){
if(!cacheExistsChecker(result)){
returnCacheAction.setRanksLists().then(function(){
returnresult;
});
)
returnresult;
}).then(function(result){
return{dailyRank:result...,weekliRank:....};
});
顺便说说题主代码里的另外几个问题
任何时候,只要构造了一个promise出来,要么return出去让调用者处理,要么自己.done掉把异常搞定。没有被.done掉的promise和try{dangerousAction()}catch{//donothing}是差不多的概念。调试噩梦
看上去代码里的exports就是RankAction(所以才会有调用自己之类的)。那么为啥缓存不命中的时候要调自己走一下命中的分支呢?结果的话不用额外调用,在自己的scope里面就有result啊
当缓存的CacheAction为啥都没有接收到查询结果result?无论实际上怎么传值过去,这样的耦合都不妙。显式要好于隐式&全局变量是恶魔
最后但其实最重要的问题,如果cacheExistsChecker就是负责检查缓存是否命中的判断,把对应的if语句放在get后面的话,这完全称不上是缓存,无论命中与否都会查redis了啊……缓存读的伪代码一般是returncacheHit()?cacheGet():(cacheSet(result=dbGet()),result)是否hit肯定要最早就判断嘛
                            
查看完整回答
反对 回复 2019-04-09
?
慕莱坞森

TA贡献1810条经验 获得超4个赞

问题好不清晰
调totalrank返回的是trDeferred的promise,也就是说当你再调该promise的then时,trDeferred把resolve的值也就是你声明里的result传给then
没有什么第一次第二次,你只调一次totalrank当然只有一个trdederred,then跟totalrank又没关系
                            
查看完整回答
反对 回复 2019-04-09
  • 2 回答
  • 0 关注
  • 568 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信