onkami
onkami

Reputation: 9411

How to correctly chain promises in complex resource loading sequence?

In angular code, I have a chained promise like this:

// a function in LoaderService module.
var ensureTypesLoaded= function(){
   return loadContainerTypes($scope).then(loadSampleTypes($scope)).then(loadProjectList($scope)).then(loadSubjectTypes($scope));
 }

Each of these functions return a promise, that loads things from a resource and additionally modifies $scope on error and success, e.g.:

         var loadProjectList = function ($scope) {

            // getAll calls inside a resource method and returns promise.
            return   ProjectService.getAll().then(
                function (items) {
                   // succesfull load
                    console.log("Promise 1 resolved");
                    $scope.projectList = items; 
                }, function () {
                    // Error happened
                    CommonService.setStatus($scope, 'Error!');
                });
        };

I intent to use in in a code in a controller initialziation as such:

// Part of page's controller initialization code
LoaderService.ensureTypesLoaded($scope).then(function () {
            // do something to scope when successes
             console.log("I will do something here after all promises resolve");
            }, function () {
            // do something when error 
            });

However, this does not work as I'd like to. Ideally message "I will do something here after all promises resolve" must appear after all promises resolve. Instead, I can see that it appears earlier than messages from resolved promises within functions that are listed ensureTypesLoaded.

I would like to create a function ensureTypesLoaded such, that:

Please help me with correct building of chained promises.

Upvotes: 0

Views: 492

Answers (1)

farincz
farincz

Reputation: 5173

I thinks that problem is in your loadProjectList function. Because .then() should receive function which is called at resultion time. Usually is function returning chain promise.

But in your case you call all load immediately in parallel. It's little complicated with $scope passing. But I think your code should appear like this

//this fn is called immediatly on chain creation
var loadProjectList = function ($scope) {  
     //this fn is called when previous promise resolves
     return function(data) {
          //don't add error handling here
          ProjectService.getAll().then(...)
     }
}

This cause serial loading as you probably want. (just notice: for parallel excution in correct way $q.all is used)

Finally you should have error handler only in ensureTypesLoaded, not in each promise.

Upvotes: 1

Related Questions