0

I have this bit of code:

for (var i = 0; i < $scope.groups.length; i++) {
                        $http.post('/api/projects/' + data.Project.Id + '/recruiting-groups', angular.toJson($scope.groups[i]))
                            .then(function (response) {
                                console.log(response.data.Data[0])
                                $scope.groups[i] = response.data.Data[0];
                            })
                            .catch(function(err) {
                                var errorMsg = "Error saving recruiting group. Contact support.";
                                $.jGrowl(errorMsg, { header: 'Error' });
                                error = true;
                            });
                    }

Works and saves just fine. BUT instead of overwriting my $scope.groups[i] it creates a duplicate.

Before Save:>

enter image description here

After Save:> enter image description here

I have checked $scope.groups too in a log and sure enough its duped. Why? How do I fix it?

Community
  • 1
  • 1
allencoded
  • 7,015
  • 17
  • 72
  • 126
  • 1
    Did you debug what the value of `i` would be ? this is a closure issue – PSL Aug 26 '14 at 14:55
  • Your `$http.post()` calls are all async. The value of `i` is probably not what you are expecting unless `$scope.groups.length` happens to be 1. – Josh C. Aug 26 '14 at 15:00
  • Ah so I should just subtract 1 from i? $scope.groups[i-1] – allencoded Aug 26 '14 at 15:00
  • http://stackoverflow.com/questions/111102/how-do-javascript-closures-work – PSL Aug 26 '14 at 15:01
  • 2
    Your for..loop would have run before your async calls are done. which mean you will be trying to update `scope.groups[scope.groups.length]`. Simple way to fix put your http cann in a method and take `index(i)` as argument and invoke that method in a loop. http://plnkr.co/edit/Nc4M9s?p=preview – PSL Aug 26 '14 at 15:02
  • That fixed it PSL if you post as answer I will accept it as chosen answer – allencoded Aug 26 '14 at 15:40
  • Sure added as answer... Thx – PSL Aug 26 '14 at 16:06

1 Answers1

1

You have a classic issue of accessing shared variable inside async calls. By the time your async calls are run for loop would have run out and i will have the last value of iteration. i.e in your case i will be $scope.groups.length. So workaround it to have your callbacks get its own iteration instance of i and not the shared i. Also it is probably a good idea to re-factor your calls as well.

One simple way is to make your calls from a function.

for (var i = 0, l=$scope.groups.length ; i < l; i++) {
  performRequest(i);
}
function performRequest(i){
    $http.post('/api/projects/' + data.Project.Id + '/recruiting-groups', angular.toJson($scope.groups[i]))
        .then(function (response) {
            $scope.groups[i] = response.data.Data[0];
        })
        .catch(function(err) {
            var errorMsg = "Error saving recruiting group. Contact support.";
            $.jGrowl(errorMsg, { header: 'Error' });
            error = true;
     });
}

But of course a more cleaner way would be:-

angular.forEach($scope.groups, performRequest)

function performRequest(group, i){
    $http.post('/api/projects/' + data.Project.Id + '/recruiting-groups', angular.toJson(group))
    .then(function (response) {
      angular.extend(group, response.data.Data[0]); //or $scope.groups[i] = response.data.Data[0];
    })
    .catch(function(err) {
        var errorMsg = "Error saving recruiting group. Contact support.";
        $.jGrowl(errorMsg, { header: 'Error' });
        error = true;
    });
} 
PSL
  • 123,204
  • 21
  • 253
  • 243