0

I have a feeling that this is a very basic error, but I've spent a couple of days reading articles/books about scope in JavaScript, returning to this problem, and still not really achieving any clarity, let alone a working solution – so its time to throw myself upon your mercy. I've looked at the other questions/answers, of course, but they seem to be referring to different kinds of scope problems, or at least studying them hasn't brought me any closer to a solution, so I though I'd risk asking for myself.

This function is supposed to take a list of filenames, then iterate over the list retrieving the files themselves and passing the contents to another function, which itself returns a javascript object representing the file content. As noted in the comments, this method itself works – when articles[i] is created inside the loop, articles[i].body contains exactly the data it should. But, by the time the loop is finished, somehow the array is empty again. Is anyone able to tell me what I've done wrong?

    // Returns an array of processed article objects
    function processAllArticles(dirname, res) {
      fs.readdir(dirname, function(err, filenames) {
        if (err) {
          onError(err);
          return;
        }
        var articles = []; // I think this is in the wrong scope?
        // Array.foreach is 95% slower than a regular for loop apparently
        for (var i = 0, len = filenames.length; i < len; i++) {
          //console.log(filenames[i]); // This part seems to work
          var currentFilePath = dirname + '/' + filenames[i];
          //console.log("Trying to pass in " + currentFilePath);
          fs.readFile(currentFilePath, function(err, content) {
            articles[i] = processArticle(content)
            // The article object seems to exist in here
            // console.log(articles[i].body);
          });
          console.log("Articles array after iteration = " + articles); //Empty
          console.log("Articles["+ i + "] = " + articles[i]); // Undefined.
        } // end loop
        console.log("ready to render " + articles.length + " article objects.");
        // articles is empty at this point ugh so nothing is being rendered
        res.render('index', { articles: articles });
      });
    }
Toadfish
  • 1,112
  • 1
  • 12
  • 22
  • 3
    It's not a scope-, it's an execution order problem. – Bergi Feb 03 '16 at 09:51
  • 1
    fs.readFile is async.... you re console.logging articles when the readFile is still running – Vanojx1 Feb 03 '16 at 09:54
  • 1
    you can refer this http://stackoverflow.com/questions/10058814/get-data-from-fs-readfile/10058879#10058879 – AKHIL K Feb 03 '16 at 09:56
  • 1
    Well, the program flow is not the same as it looks. First, the whole loop gets executed, then `console.log` lines and `res.render`, and only then, after the file is read, the callback for `fs.readFile` gets executed. – Microfed Feb 03 '16 at 09:57
  • 1
    Execute res.render and console.logs in readFile callback with a check `if (i == len-1) {` it will be the last call. – jcubic Feb 03 '16 at 10:03
  • @jcubic thanks a lot, I know I should really be using promises or something a little more elegant but this solution is perfect given this learning exercise won't ever be used in production – Toadfish Feb 04 '16 at 04:15

0 Answers0