这个promise嵌套可以改成chaining吗? [英] Can this promise nesting be changed to chaining?

查看:27
本文介绍了这个promise嵌套可以改成chaining吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是伪场景

           | then (items)          | then (items, actions)
getItems() | getActions(for:items) | apply(actions -> items)
 :promise  |  :promise             | model <= items
           |                       |  :synchronous

一句话:

  1. 我需要获取全局项目列表.
  2. 好的.已获取项目.
  3. 请求用户对之前获取的项目采取的操作.
  4. 好的.已获取操作.
  5. 将操作应用于项目列表.
  6. 将物品放在模型上并显示在视图中.

这是我正在使用的代码

return itemsResource
       .getItems(userId)
       .$promise
       .then(function(items) {
           return actionsResource
                  .getActions(items.map(i => i.id)) // pseudo mapper code here
                  .$promise
                  .then(function(actions) { // THIS IS NESTED so it sees both promise results
                      return [items, actions];
                  });
       })
       .then(helper.spread(function(items, actions) {
           applyActions(items, actions);
           $scope.model.items = items;
           return items;
       }));

如您所知,我最初不能使用 $q.all,因为第二个(操作)承诺取决于第一个(项目)的结果.

As you can understand I can't use $q.all initially because second (actions) promise depends on results of the first one (items).

为什么不返回带有项目的操作?因为我正在为所有用户缓存项目,所以项目获取非常快.这类似于 Stackoverflow 的工作方式.无论用户提出什么要求,他们都只会返回问题.然后他们随后还请求首选和忽略的标签并应用于获取的问题.这可以很好地扩展,否则 SO 将需要更多的服务器来处理所有用户的初始问题列表,因为每个用户的请求会产生不同的结果,因此缓存没有多大意义.

Why not return actions with items? Because I'm caching items for all users, so item fetching is really quick. This is similar to how Stackoverflow works. They just return questions regardless of user requesting them. Then they subsequently also request for preferred and ignored tags and apply to fetched questions. This scales very well, otherwise SO would require many more servers to handle just initial list of questions for all users, because every user's request would yield different results, so caching wouldn't make much sense.

为什么不在获取后立即将项目应用到 $scope? 这将消除额外的嵌套 then,这是真的.但我没有这样做,因为之后还有几个步骤,每次解决一个承诺时,至少会执行一个 $digest 循环.对于许多项目(相当复杂的对象),这可以解释相当多的处理.这就是我坚持将项目传递到视图直到可能的最后一刻的原因.

Why not apply items to $scope immediately after being fetched? This would eliminate the additional nested then, that's true. but I'm not doing that because there are few more steps afterwards and every time one of the promises gets resolved at least one $digest cycle is being executed. With many items (being rather complex objects) this can account for quite some processing. That's the reason I'm holding on to passing items to the view to the very last moment possible.

有没有办法避免除了这两种解决方法之外的嵌套 then :

Is there a way to avoid the nested then beside these two workarounds:

  1. 尽快将项目应用到 $scope
  2. 将项目保存到局部变量并在之后使用

如果可能的话,我想在不引入额外资源的情况下尽可能地扁平化我的代码?

I'd like to flatten my code as much as possible without introduction of additional resources if possible?

推荐答案

除非我遗漏了什么,否则这应该相当简单,不是吗?

Unless I'm missing something, this should be fairly straightforward, no?

(为了清楚起见,我简化了您的一些内部函数签名)

(I have simplified some of your internal function signatures for clarity)

itemsResource.getItems(userId)
  .then(function(items) {
    return $q.all({
      items: items,
      actions: actionResource.getActions(items)
    });
  })
  .then(function(data) {
    applyActions(data.items, data.actions);
    $scope.model.items = data.items;
    return data.items;
  });

plunker 用于说明

这篇关于这个promise嵌套可以改成chaining吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆