这是伪方案
| then (items) | then (items, actions)
getItems() | getActions(for:items) | apply(actions -> items)
:promise | :promise | model <= items
| | :synchronous
所以用语言说:
这有点像我使用的代码
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
,因为第二个(行动)承诺取决于第一个(项目)的结果。
为什么不通过项目返回操作?因为我为所有用户缓存了项目,所以项目提取非常快。这与Stackoverflow的工作方式类似。无论用户是否请求,他们都会返回问题。然后,他们随后还会请求首选和忽略的标签,并应用于提取的问题。这很好地扩展,否则SO将需要更多的服务器来处理所有用户的初始问题列表,因为每个用户的请求将产生不同的结果,因此缓存不太有意义。
为什么不在提取后立即将项目应用到$scope
?这将消除额外的嵌套then
,这是真的。但是我没有这样做,因为之后几乎没有其他步骤,每次一个承诺得到解决,至少有一个$digest
周期正在执行。对于许多项目(相当复杂的对象),这可以解释相当多的处理。这就是我在最后一刻坚持将物品传递到视野的原因。
除了这两种解决方法之外,有没有办法避免嵌套then
:
$scope
如果可能的话,我希望在不引入额外资源的情况下尽可能地展平我的代码?
答案 0 :(得分:2)
除非我遗漏了什么,否则这应该是相当简单的,不是吗?
(为了清楚起见,我简化了一些内部功能签名)
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用于说明
答案 1 :(得分:0)
如何在promise中包含items-&gt;动作链的结果?像
这样的东西return $q(function(resolve, reject) {
var outerItems;
itemsResource.getItems(userId).$promise
.then(getActions)
.then(function (actions) {
resolve([outerItems, actions]);
})
.catch(function (err) { reject(err); });
function getActions(items) {
outerItems = items;
return actionsResource.getActions(items).$promise
}
}).then(function (itemAndActions) {
var items = itemsAndActions[0],
actions = itemsAndActions[1];
return helper.spread(function (items, actions) {
applyActions(items, actions);
$scope.model.items = items;
return items;
})
});