Batman
Batman

Reputation: 6353

Promises not running in order

I have a function in my controller that adds users to a group, Once a user has been assigned to a group, the list of groups available should decrease. I tried using promises in my function to control the flow but based on the console log, all my groupServices are running first, then the userServices are running after, preventing the list of Available groups to update correction.

Controller Function:

    $scope.addUserToGroup = function (){
        var defer = $q.defer();
        defer.promise.then(function (){
            userService.addUserToGroup(
                $scope.selectedUser, 
                $scope.selectedAvailableGroups, 
                $scope.assignedGroups, 
                $scope.availableGroups,
                $scope.groups
            ); 
        }).then(compare());
        defer.resolve();
    };
    function compare(){
    console.log('comparing assigned with all ');
        $scope.compareGroups = groupService.compareGroups();         
    }

I'm using promises trying to make sure things run in order but based on my console output it doesn't seem to be the case.

User Service function

  var addUserToGroup = function (selectedUser, selectedAvailableGroups, assignedGroups, availableGroups, groups){

    console.dir(selectedUser);
    console.dir(selectedAvailableGroups);
    console.dir(assignedGroups);
    console.dir(availableGroups);
    console.dir(groups);

    var deferred = $q.defer();

    var addPromise = [];
    var selectLength = selectedAvailableGroups.length;

    //Add user to selected groups on server
    deferred.promise
      .then(function (){ 
        for (var i = 0; i < selectLength; i++){
          addPromise[i] = $().SPServices({
            operation: "AddUserToGroup",
            groupName: selectedAvailableGroups[i].name,
            userLoginName: selectedUser.domain
          });      
        }; 
      })
      .then(function (){
          //when promise finished, push changes to availableGroups
          for (var i = 0; i < selectLength; i++){
            assignedGroups.push(selectedAvailableGroups[i]);
            console.log(selectedUser.name + " added to: " + selectedAvailableGroups[i].name);
          };
      });
    //Run
    deferred.resolve();
  }

Group Service function:

var compareGroups = function () {
    //Comparing assigned groups with allGroups to return available groups
    var assignedGroupsIds = {};
    var groupsIds = {};
    var result = []
    availableGroups = [];
    console.log('assigned');
    console.dir(assignedGroups);
    console.log('avail');

    assignedGroups.forEach(function (el, i) {
        assignedGroupsIds[el.id] = assignedGroups[i];
    }); 

    allGroups.forEach(function (el, i) {
        groupsIds[el.id] = allGroups[i];
    });   

    for (var i in groupsIds) {
        if (!assignedGroupsIds.hasOwnProperty(i)) {
            result.push(groupsIds[i]);
            availableGroups.push(groupsIds[i]);

        }
    };
    console.dir(result);
    console.dir(availableGroups);
}

Console Log:

comparing assigned with all  userCtrl.js:47
assigned groups             groupServices.js:63
Array[8]                    groupServices.js:64
available gruops            groupServices.js:65
Array[3]                    groupServices.js:82
Array[3]                    groupServices.js:83
Object                      userServices.js:38
Array[1]                    userServices.js:39
Array[8]                    userServices.js:40
Array[4]                    userServices.js:41
Array[11]                   userServices.js:42
User added to: Test Group 4 userServices.js:64

Upvotes: 3

Views: 735

Answers (1)

user2445933
user2445933

Reputation:

You are using promises in wrong way.

The first problem is here:

}).then(compare());

You are trying to register result of execution of compare function as a callback, instead of registering just compare function like this:

}).then(compare);

That's why it executes first, then calls groupService.compareGroups() and only after it completes, you are calling defer.resolve() and your first registered callback executes. That's why you see your current console output.

You need to modify User Service and Controller in following way to get it work (Using $q service to work with promises):

Controller function:

function compare(){
    console.log('comparing assigned with all ');
    $scope.compareGroups = groupService.compareGroups();         
}

$scope.addUserToGroup = function (){
    userService.addUserToGroup(
        $scope.selectedUser, 
        $scope.selectedAvailableGroups, 
        $scope.assignedGroups, 
        $scope.availableGroups,
        $scope.groups
    ).then(compare); 
};

User Service function:

(Assuming, that $().SPServices returns Promise)

var addUserToGroup = function (selectedUser, selectedAvailableGroups, assignedGroups, availableGroups, groups){

    console.dir(selectedUser);
    console.dir(selectedAvailableGroups);
    console.dir(assignedGroups);
    console.dir(availableGroups);
    console.dir(groups);

    var deferred = $q.defer();

    var addPromise = [];
    var selectLength = selectedAvailableGroups.length;

    //Add user to selected groups on server
    for (var i = 0; i < selectLength; i++){
        addPromise[i] = $().SPServices({
            operation: "AddUserToGroup",
            groupName: selectedAvailableGroups[i].name,
            userLoginName: selectedUser.domain
        });      
    }

    $q.all(addPromise).then(function (){
        //when promise finished, push changes to availableGroups
        for (var i = 0; i < selectLength; i++){
            assignedGroups.push(selectedAvailableGroups[i]);
            console.log(selectedUser.name + " added to: " + selectedAvailableGroups[i].name);
        };

        //Finish function
        deferred.resolve();
    });
    return deferred.promise;
}

Upvotes: 5

Related Questions