user231124ns11
user231124ns11

Reputation: 117

Mutable Variable is in accessible from closures

I'm new to javascript. Here is my code

  ......
var filename, result, user=["a", "b", "c","d"];
for(var p=0;p<user.length;p++)
      {
       filename=userID[p]+'_'+user[p]+'.json';

       fs.readFile(filename, function read(err, data)
       {
           if (err) {throw err;}
           result = data.toString();

            if (result.charAt(result.length-1) === ',')
             result = result.substring(0,result.length-1) + ']}';

          console.log(p+filename+result+"\n\n"); //here

            });

         }

In "here" the value of p is always showing the last index, in this case 3 in for all iterations also the filename is the for the last iteration.How can I get the correct value of p in "here". For p my compiler shows "Mutable Variable is in accessible from closures".

Upvotes: 1

Views: 91

Answers (2)

hoangdv
hoangdv

Reputation: 16147

In this case scope of filename is for loop block, filename value have bind to fs.readFile. Simple way to fix this, follow the block code

var filename, result, user = ["a", "b", "c", "d"];
for (var p = 0; p < user.length; p++) {
    filename = userID[p] + '_' + user[p] + '.json';

    (function(file) {
        fs.readFile(filename, function read(err, data) {
            if (err) {
                throw err;
            }
            result = data.toString();

            if (result.charAt(result.length - 1) === ',')
                result = result.substring(0, result.length - 1) + ']}';

            console.log(p + filename + result + "\n\n"); //here

        });

    })(filename)

}

Upvotes: 1

Nisarg Desai
Nisarg Desai

Reputation: 371

@naomik comment seems right any asynchronous job with in body of loop is always bad idea. because loop will not wait till response.

var filename, result, user=["a", "b", "c","d"];
var p=0;
 function readfileUnitil(p)
  {
   filename=userID[p]+'_'+user[p]+'.json';

   fs.readFile(filename,function(err, data)
   {
       if (err) {throw err;}
       result = data.toString();

        if (result.charAt(result.length-1) === ',')
         result = result.substring(0,result.length-1) + ']}';

      console.log(p+filename+result+"\n\n"); //here
        if(p<user.length){
         p++;
         readfileUnitil(p);
        }
        });
   }
 }

i do prefer this kind of recursion instead of let variable as this is more readable and memory will not held by browser hope that helps.

Upvotes: 1

Related Questions