incremental UI updates from multiple promises
angularjs, promise
Solution
You could use your own promise to return and then hook into a notification of the promise to give you an update on the overall loading progress, and still use `$q.all` to determine when this has finished. It is basically what you have now with slightly different way of handling and using a custom promise.
Fiddle: http://jsfiddle.net/U4XPU/1/
HTML
<div class="wrapper" ng-app="stackExample">
<div class="loading" ng-show="loading">Loading</div>
<div class="contacts" ng-controller="ContactController">
<div class="contact" ng-repeat="contact in contacts"> {{contact.name}} - {{contact.dob}}</div>
</div>
</div>
Controller
.controller("ContactController", ["$scope", "CollectionService", function (scope, service) {
scope.contacts = [];
scope.loading = true;
service.fetch("/contacts")
.then(
// All complete handler
function () {
console.log("Loaded all contacts");
scope.loading = false;
},
// Error handler
function () {
scope.error = "Ruh roh";
scope.loading = false;
},
// Incremental handler with .notify
function (newContacts) {
console.log("New contacts found");
scope.contacts = scope.contacts.concat(newContacts);
});
}])
Service
.service("CollectionService", ["$q", "$http", function (q, http) {
this.fetch = function (collectionUrl) {
var deferred = q.defer();
http.get(collectionUrl)
.then(function (response) {
// Still map all your responses to an array of requests
var allRequests = response.data.map(function (url) {
return http.get(url)
.then(function (innerResponse) {
deferred.notify(innerResponse.data);
});
});
// I haven't here, but you could still pass all of your data to resolve().
q.all(allRequests).then(function () {
deferred.resolve();
});
});
return deferred.promise;
}
}]);
You can also handle the errors as you see fit and `.reject()` the promise:
http://docs.angularjs.org/api/ng/service/$q
Problem
I have an AngularJS service that's used to retrieve individual contacts (`/contacts/:id`) based on an index (`/contacts`): ``` app.service("CollectionService", function($http, $q) { this.fetch = function(collectionURL) { return $http.get(collectionURL).then(function(response) { var urls = response.data; var entities = urls.map(function(url) { return $http.get(url); }); return $q.all(entities); }).then(function(responses) { return responses.map(function(response) { return response.data; }); }); }; }); // used within the controller: CollectionService.fetch("/contacts").then(function(contacts) { $scope.contacts = contacts; }); ``` The results are displayed in a simple list (`<li ng-repeat="contact in contacts">{{ contact }}</li>`). However, due to the use of `$q.all`, that list is not updated until the last (slowest) response has been received. How would one switch from this bulk update to incremental updates as individual contacts are received?