3

I have a simple nested callback utilizing the Node FileSystem module and I'm having a hard time trying to get access to a variable that I feel is only made available due to the scope chain. My goal is to reduce nested callbacks as much as possible.

var fs = require('fs');
var directory = '/Users/johndoe/desktop/temp';

fs.readdir(directory, function(err, files) {
  files.forEach(function(file) {
    var filePath = directory + "/" + file;
    fs.readFile(filePath, function(err, data) {
      // I have access to filePath variable here.  This works just fine.
      console.log(filePath);
    });
  });
});

But this is what I would like to write instead:

var fs = require('fs');
var directory = '/Users/johndoe/desktop/temp';

fs.readdir(directory, processFiles);

function processFiles(err, files) {
  files.forEach(function(file) {
    var filePath = directory + "/" + file;
    fs.readFile(filePath, processSingleFile);
  });
}

function processSingleFile(err, data) {
  // how do I get the filePath variable here?
  console.log(filePath);
}

How do I get the filePath variable here in the second example?

4
  • just use console.log(data); in your processSingleFile function. :) Commented Sep 16, 2015 at 4:29
  • Use promises to reduce nested callbacks and chain the request Commented Sep 16, 2015 at 4:31
  • You can use a global variable. Commented Sep 16, 2015 at 4:34
  • @AdityaParab, data is the contents of the file, not the name of the file. Commented Sep 16, 2015 at 4:34

4 Answers 4

4

You can pass filePath as the first parameter to processSingleFile by binding it.

function processFiles(err, files) {
  files.forEach(function(file) {
    var filePath = directory + "/" + file;
    fs.readFile(filePath, processSingleFile.bind(this, filePath));
  });
}

function processSingleFile(filePath, err, data) {
  console.log(filePath);
}
Sign up to request clarification or add additional context in comments.

Comments

1

Change processSingleFile to a function returning function and pass variable filePath as a variable to that. Like bellow

function processSingleFile(filePath) {
  return function(err, data){
    console.log(filePath);
    console.log(data);
  }
}

call it like bellow

fs.readFile(filePath, processSingleFile(filePath));

4 Comments

That's a nested callback, you just nested it in a different function.
@RaymondChen I don't think this nesting is bad. It's just a wrapper.
@RaymondChen technically the solution you accepted which binds a function is just another way of scoping it. What happens internally is it becomes a wrapper function to the original function and passes the arguments differently. So any solution you use will have some sort of scoping.
@PatrickRoberts Of course it's scoping. But binding is scoping without using a nested function (because for some reason the OP doesn't like nested functions).
0
var fs = require('fs');
var directory = '/Users/johndoe/desktop/temp';

fs.readdir(directory, processFiles);

// declaring filePath outside to allow scope access
var filePath;

function processFiles(err, files) {
  files.forEach(function(file) {
    filePath = directory + "/" + file;
    fs.readFile(filePath, processSingleFile);
  });
}

function processSingleFile(err, data) {
  // You can access filePath here
  console.log(filePath);
}

2 Comments

Mind you, I have just started working with node, so I can not say if this is the right way of doing it
That doesn't work once you have more than one file in the directory.
0
function processFiles(err, files) {
  files.forEach(function(file) {
    var filePath = directory + "/" + file;
    fs.readFile(filePath, function(err,data){
        processSingleFile(data,filePath);
    });
  });
}

function processSingleFile(data, filePath) {
  // You can access filePath here
  console.log(filePath);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.