0

I'm trying to refactor my code a bit to make it a little nicer to use. What I would like to do is take a Node callback and pass back the result or error as a JavaScript object. It appears the scoping rules are preventing me from doing this, so is there a somewhat straightforward way to do this or am I stuck inside of the callback (unless I do something funky like implementing Promises in JavaScript, which Google Search reveals is what all the cool kids are doing these days)?

I'm still not all that comfortable with JavaScript - I think there is probably an easier way to do this and I'm just not getting it because I haven't worked with it enough (I know with jQuery I can set 'this' within a promise to get access to my outer scope, for example, but I'm not sure how to do this with Node, or if I can).

/*
 * Retrieves the full list of only the files, excluding subdirectories, in the directory provided.
 *
 * Parameters:
 *   dir: The directory to get the file list from.
 *
 * Return: An object containing either an error message or the fileList as a String array.
 *   e.g.
 *   { errMsg: undefined,
 *     fileList: ["file1.txt", "file2.xlsx"]
 *   }
 */
var getFileList = function (dir) {
  var filterOutDirectories = function (files) {
        return files.map(function (file) {
          return path.join(dir, file);
        }).filter(function (file) {
          return fs.statSync(file).isFile();
        });
      };
  var result = {
    errMsg: null,
    fileList: null
  };

  fs.readdir(dir, function (err, files) {
    if (err) {
      result.errMsg = "Error: Could not retrieve files...\n\t" + err;
    } else {
      result.fileList = filterOutDirectories(files);
    }
  });

  console.log(result.fileList); // returns null
  console.log(result.errMsg); // also returns null

  return result;
}
josiah
  • 1,314
  • 1
  • 13
  • 33
  • 1
    You don't have to *implement* promises, you just have to *use* them :-) – Bergi Feb 25 '15 at 01:27
  • 1
    Yes, you're stuck with callbacks when you're doing asynchronous stuff in JavaScript. No way around it. – Bergi Feb 25 '15 at 01:28

1 Answers1

1

the readdir is an async call, so the variables that are set in the callback are not available directly after the call.

  • If your program logic can't move forward without the results of the directory, you can use readdirSync. The reason to use async calls is if your program can do something useful before the return. You can also add a callback to the outer function so that the function doesn't return result, but passes it as a parameter in a call to the outer function's callback. – Randy Kamradt Sr. Feb 25 '15 at 01:35
  • I think the readdirSync method would be the right answer, here. I'm really just providing a file list straight back to in the REST reply. However, would this limit the ability of Express to handle multiple simultaneous requests to that url? – josiah Feb 25 '15 at 02:19
  • Is the reason these variables aren't available simply because the callback is contained within the context of the `fs` object? – josiah Feb 25 '15 at 02:20
  • The callback is called at a different time. That is the purpose of a callback, to say what you are going to do when the operation completes. It is a common error to read the code as if it executes from top to bottom, but it doesn't, any code contained in an callback style function is not executed until sometime later. – Randy Kamradt Sr. Feb 25 '15 at 02:30