title: Node - how to wait on async operations?
body: <p>Sorry, just starting with node.  This might be a very novice question.</p>
  
  <p>Let's say I have some code which reads some files from a directory in the file system:</p>
  
  <pre><code>var fs = require('fs');
  
  fs.readdir(__dirname + '/myfiles', function (err, files) {
      if (err) throw err;
      files.forEach(function (fileName) {
          fs.readFile(__dirname + '/myfiles/' + fileName, function (err, data) {
              if (err) throw err;
              console.log('finished reading file ' + fileName + ': ' + data);
              module.exports.files.push(data);
          });
      });
  });
  </code></pre>
  
  <p>Note that all of this occurs asynchronously.  Let's also say I have a Mocha test which executes this code:</p>
  
  <pre><code>describe('fileProvider', function () {
      describe('#files', function () {
          it.only('files array not empty', function () {
              assert(fileProvider.files.length &gt; 0, 'files.length is zero');
          });
      });
  });
  </code></pre>
  
  <p>The mocha test runs before the files are finished being read.  I know this because I see the console.log statement after I see the little dot that indicates a mocha test being run (at least I think that is what is being indicated).  Also, if I surround the assert with a setTimeout, the assert passes.</p>
  
  <p>How should I structure my code so that I can ensure the async file operations are completed?  Note that this is not just a problem with testing - I need the files to be loaded fully before I can do real work in my app as well.</p>
  
  <p>I don't think the right answer is to read files synchronously, because that will block the Node request / response loop, right?</p>
  
  <p><strong>Bonus question:</strong><br>
  Even if I put the assert in a setTimeout with a 0 timeout value, the test still passes.  Is this because just putting it in a setTimeout kicks it to the end of the processing chain or something so the filesystem work finishes first?</p>