This situation is just a scenario
| then (items) | then (items, actions)
getItems() | getActions(for:items) | apply(actions -> items)
:promise | :promise | model <= items
| | :synchronous
In simpler terms:
- I have to retrieve a list of global items.
- Okay. Items retrieved.
- Request for actions taken on the items fetched previously by the user.
- Alright. Actions received.
- Apply actions to the items list.
- Add items to the model and show in view.
This is more or less what my code looks like
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;
}));
You can see that I cannot use $q.all
initially because the second (actions) promise relies on the results of the first one (items).
Why not include actions with items? Because I'm caching items for all users, making item fetching quick. This is similar to how Stackoverflow operates. They provide questions regardless of who requests them. Later, they request preferred and ignored tags to apply to the fetched questions. This system scales efficiently, saving on server resources as every user's request would be different otherwise.
Why not display items in $scope
right after fetching? This would remove the additional nested then
, but I refrain from doing so since there are more steps to follow. Each time a promise resolves, at least one $digest
cycle is executed. With many complex items, this processing can add up. Hence, I delay passing items to the view until absolutely necessary.
Query
Is there a way to eliminate the nested then
without resorting to these two alternatives:
- Show items in
$scope
as soon as possible - Save items locally for later use
I aim to simplify my code while minimizing additional resources, if possible?