Home » Nodejs » Best way to pass variables into callback functions in Node.js

Best way to pass variables into callback functions in Node.js

Posted by: admin November 29, 2017 Leave a comment

Questions:

I’ve been wondering, is there a better way to pass variables into callback functions in node.js other than using bind().

Here is an example:

var fs = require('fs');

for(var i = 0; i < 100; i++) {
    fs.writeFile(i + ".txt", i, function(error) {
        fs.stat(this.i + ".txt", function() {
            fs.rename(this.i + ".txt", this.i + ".new.txt", function() {
               console.log("[" + this.i + "] Done...");
            }.bind({ i: this.i }));
        }.bind({ i: this.i }));
    }.bind({ i: i }));
}

Notice the bind() methods all the way up, simply passing the value of i.

Thanks.

Answers:

Variables in JavaScript are valid for the whole function scope.
This means that you can define a variable x ((var x = ...) and it is still accessible in all functions, you define within the same calling scope.
(For detailed information you might want to take a look at JavaScript Closures

The problem of your case is, that you manipulate your i during the for loop.
If simply access the i in the callback functions, you’d recieve the first value that is no longer in the loop.

You can avoid that by calling a new function with the i as argument, like this:

var fs = require('fs');

// still use your for-loop for the initial index
// but rename i to index to avoid confusion
for (var index = 0; index < 100; index++) {
  // now build a function for the scoping
  (function(i) {
    // inside this function the i will not be modified
    // as it is passed as an argument
    fs.writeFile(i + ".txt", i, function(error) {
      fs.stat(i + ".txt", function() {
        fs.rename(i + ".txt", i + ".new.txt", function() {
          console.log("[" + i + "] Done...");
        });
      });
    });
  })(index) // call it with index, that will be i inside the function
}

Questions:
Answers:

I would like to do with below:

var fs = require('fs');

var getWriteFileCallback = function(index) {
  return function(error) {                           
    fs.stat(index + '.txt', function() {             
      fs.rename(index + '.txt', index + '.new.txt', function() {
        console.log("[" + index + "] Done...");      
      });                                            
    });                                              
  };                                                 
}                                                    

for(var i = 0; i < 100; i++) {
  fs.writeFile(i + ".txt", i, getWriteFileCallback(i));
}

Questions:
Answers:

You can use let instead of var in your for loop. This is (in my eyes at least) the biggest difference between the two!
Just make sure you use strict mode or let won’t work for you.

var fs = require('fs');

for(let i = 0; i < 100; i++) {
    fs.writeFile(i + ".txt", i, function(error) {
        fs.stat(i + ".txt", function() {
            fs.rename(i + ".txt", i + ".new.txt", function() {
               console.log("[" + i + "] Done...");
            });
        });
    });
}