-1

I think that I am an idiot. What is happening here?? Why there is no i:0 or i:1, just only the last one? It shows that it loops everything and just after looping it tries to save and it is saving the same last object many time and after that I'll get error 500, duplicate key in DB. Is it even possible to save objects inside the for loop :) in AngularJS?

In console.log:

reasonList.length: 2
rma.js: 284 i: 2
rma.js: 285 defectdescDefectdescId: 2
rma.js: 286 returnreasonId: 1
rma.js: 287 rmaId: 15

code:

        savedRma = rmaService.save({}, rma);
        savedRma.$promise.then(function (result) {
            $scope.rma = result;
            console.log('result.rmaID--------->' + result.rmaId);
            saveReturnReason(result.rmaId);
        }, function (error) {
            alert('Error in saving rma' + error);
        });
        $location.path('/rma-preview/' + $scope.rma.rmaId);
        rmaDataService.setRma($scope.rma);
    }
}; // ELSE CREATE RMA END
function saveReturnReason(rmaId) {
    for (var i = 0; i < $scope.reasonList.length; i++) {
        $scope.rmaHasDefectdesc.rmaHasDefectdescPK.defectdescDefectdescId = $scope.reasonList[i].defectdescId;
        $scope.rmaHasDefectdesc.rmaHasDefectdescPK.returnreasonId = $scope.reasonList[i].returnreasonReturnreasonId.returnreasonId;
        $scope.rmaHasDefectdesc.rmaHasDefectdescPK.rmaId = rmaId;
        savedRmaHasDefectdesc = rmaDefectSvc.save({}, $scope.rmaHasDefectdesc);
        savedRmaHasDefectdesc.$promise.then(function (response) {
            $scope.savedRmaHasDefectdesc = response;
            console.log('i: ' + i)
            console.log('defectdescDefectdescId:' + response.rmaHasDefectdescPK.defectdescDefectdescId);
            console.log('returnreasonId:' + response.rmaHasDefectdescPK.returnreasonId);
            console.log('rmaId:' + response.rmaHasDefectdescPK.rmaId);
        }, function (error) {
            alert('Error in saving reasons' + error);
        });
    } // For loop ending
};

UPDATE FOR forEach I updated for loop to forEach. Same result, no luck. Still not going to promise.then in first each and then tries to save the last reason multiple times.

function saveReturnReason(rmaId) {
    $scope.reasonList.forEach(function(reason){
    $scope.rmaHasDefectdesc.rmaHasDefectdescPK.defectdescDefectdescId = reason.defectdescId;
    $scope.rmaHasDefectdesc.rmaHasDefectdescPK.returnreasonId = reason.returnreasonReturnreasonId.returnreasonId;
    $scope.rmaHasDefectdesc.rmaHasDefectdescPK.rmaId = rmaId;
    console.log('rmaId: ' +rmaId+': returnReasonId: ' +reason.returnreasonReturnreasonId.returnreasonId +' defectID: '+reason.defectdescId);

    savedRmaHasDefectdesc = rmaDefectSvc.save({}, $scope.rmaHasDefectdesc);
    // At the first loop, never comes to .then
    savedRmaHasDefectdesc.$promise.then(function (response) {
         $scope.savedRmaHasDefectdesc = response;

     }, function (error) {
                            alert('Error in saving reasons' + error.status);
     });


     });// ForEach ending

};
Sami
  • 2,311
  • 13
  • 46
  • 80
  • 1
    It would be better if you formatted this code properly. – Joseph Jul 08 '15 at 17:51
  • Looks like the typical "asynchronous work in a for loop, why does `i` show last index instead of current inside a callback" – Kevin B Jul 08 '15 at 17:56
  • Please share a better formatted code and the output for this code. – Mr.Green Jul 08 '15 at 17:59
  • Possible duplicate: http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example/750506#750506 – Kevin B Jul 08 '15 at 17:59
  • @KevinB - Could you tell me how to fix this? This is annoying and I have no idea what the heck is happening there? – Sami Jul 08 '15 at 18:07
  • 1
    on an es6 browser, replacing `var i` with `let i` should fix the issue, however, to support older browsers, you'll have to either switch to Array.forEach, or use an iife or function generator inside your for loop to preserve the value of `i` within a new scope on each iteration. the highest upvoted answer at possible duplicate shows all three options. – Kevin B Jul 08 '15 at 18:09
  • @Mr.Green - output is just that what is said in console.log, nothing else. There is no i:0 or i:1. Just the last one (i:2) and then it tries to save the last object many times and I got Error 500 for duplicate key in DB. This is so strange for javaScript newbie. – Sami Jul 08 '15 at 18:10
  • tldr, the value of `i` increments on each iteration, before the asynchronous action is complete. By the time the action on each iteration is done, `i`'s value will be `$scope.reasonList.length` for all of the callbacks. – Kevin B Jul 08 '15 at 18:10

1 Answers1

0

Scope the i so that it's only available in the loop:

for (var i = 0; i < $scope.reasonList.length; i++) {
    (function(i){
        $scope.rmaHasDefectdesc.rmaHasDefectdescPK.defectdescDefectdescId = $scope.reasonList[i].defectdescId;
        $scope.rmaHasDefectdesc.rmaHasDefectdescPK.returnreasonId = $scope.reasonList[i].returnreasonReturnreasonId.returnreasonId;
        $scope.rmaHasDefectdesc.rmaHasDefectdescPK.rmaId = rmaId;
        savedRmaHasDefectdesc = rmaDefectSvc.save({}, $scope.rmaHasDefectdesc);
        savedRmaHasDefectdesc.$promise.then(function (response) {
            $scope.savedRmaHasDefectdesc = response;
            console.log('i: ' + i)
            console.log('defectdescDefectdescId:' + response.rmaHasDefectdescPK.defectdescDefectdescId);
            console.log('returnreasonId:' + response.rmaHasDefectdescPK.returnreasonId);
            console.log('rmaId:' + response.rmaHasDefectdescPK.rmaId);
        }, function (error) {
            alert('Error in saving reasons' + error);
        });
    })(i)
} // For loop ending

The problem as other people have mentioned is that your loop finishes before the promise is done, so by the time you console log the i is already updated.

Mathew Berg
  • 28,625
  • 11
  • 69
  • 90