3

I have following code:

var favourites = JSON.parse(localStorage.getItem("favourites"));

Service.all().then(function (multiple) {
        var array = [];            

        for (var i = 0; i < multiple.length; i++) {
           for (var j = 0; j < favourites.length; j++) {
              if (favourites[j].checked === true) {
                 if (multiple[i].Name === favourites[j].name) {

                    Service.getAllBySomething(multiple[i].Id).then(function (resources) {
                       var arrayOfSomething = [];

                       for (var k = 0; k < resources.length; k++) {
                                                     arrayOfSomething.push(resources[k].ResourceCategoryId);
                       }                           
                       arrayOfSomething = arrayOfSomething .filter(function (elem, pos, arr) {
                          return arr.indexOf(elem) == pos;
                       });
                       multiple[i].existingProperty= arrayOfSomething;
                    });                        
                    array.push(multiple[i]);
                 }
              }                  
           }
        }            
        $scope.vendors = array;
     });

My problem is that it says everytime 'Cannot set property existingProperty of undefined'. And I don't know why multiple[i] should be undefined at this line:

multiple[i].existingProperty= arrayOfSomething;

The property exists, I am sure. And it is defined, it is an empty array. And this empty array I want to replace with my made array in the loops. Where is the fault? How I can fill the existingProperty with my array?

user3679607
  • 163
  • 2
  • 16
  • 2
    possible duplicate of [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – JJJ Jul 17 '15 at 09:34

1 Answers1

1

is Service.getAllBySomething asynchronous by any chance? Because in that case, by the time the callback function runs, i (captured in a closure only) has been moved to the end of the array.

Use an additional closure to capture the value of i at the time of dispatching the async call, like this:

Service.getAllBySomething(multiple[i].Id).then(function(i){
     return function (resources) {
                   var arrayOfSomething = [];

                   for (var k = 0; k < resources.length; k++) {
                                                 arrayOfSomething.push(resources[k].ResourceCategoryId);
                   }                           
                   arrayOfSomething = arrayOfSomething .filter(function (elem, pos, arr) {
                      return arr.indexOf(elem) == pos;
                   });
                   multiple[i].existingProperty= arrayOfSomething;
                };
}() );    

Note the new function receiving i as a param and returning the function you previously used. I'm invoking immediately (an IIFE) to return the function to pass as callback. Inside that function the value of i will be the same as when you dispatch this async call, as it was copied when used as a parameter.

doldt
  • 4,466
  • 3
  • 21
  • 36
  • @user3679607 Can you post an [SSCE](http://sscce.org/)? (Emphasis on the self-contained) – doldt Jul 17 '15 at 10:49