Optimal design pattern - functions which process multiple files

Goal is to create distinct functions which separate out the work of loading multiple (xml) files and parsing them. I could do this all in one function, but the nested callbacks begin to get ugly. In other words, I don't want to do this:

// Explore directory
fs.readdir(path, function (err, files) {
    if(err) throw err;
        // touch each file
        files.forEach(function(file) {
           fs.readFile(path+file, function(err, data) {
             if (err) throw err;    
              someAsyncFunction ( function (someAsyncFunctionResult) {
                   // Do some work, then call another async function...
                   nestedAsynchFunction ( function (nestedAsyncFunctionResult) {
                       // Do Final Work here, X levels deep. Ouch!
                    });
                 });
             });                           
       });
});

Instead, I want one function which reads my files and puts each file's XML payload into an array of objects which is returned to the caller (each object represents the name of the file and the XML in the file). Here's the function that might load up reports into an array:

function loadReports (callback) {
    var path = "./downloaded-reports/";
    var reports = [];

    // There are TWO files in this path....
    fs.readdir(path, function (err, files) {
        if(err) throw err;
        files.forEach(function(file) {
            fs.readFile(path+file, function(err, data) {
            if (err) throw err;    
            reports.push({ report: file, XML: data.toString()});  
            //gets called twice, which makes for strangeness in the calling function    
            callback(null, reports);
            });                           
        });
        // callback won't work here, returns NULL reports b/c they haven't been processed yet
        //callback(null, reports);
    });

}

...and here's the function which will call the one above:

function parseReports() {

        loadReports( function(err, data) {   
            console.log ("loadReports callback");
            var reportXML = new jsxml.XML(data[0].XML);
            var datasources = reportXML.child('datasources').child('datasource').child('connection').attribute("dbname").toString();
            console.log(JSON.stringify(datasources,null, 2));     
            // More async about to be done below     
        } );  
}

As you can see in the loadReports() comments, I can't get the callback to work right. It either calls back BEFORE the array is has been populated at all, or it calls back twice - once for each fs.readFile operation.

SO...what is the best way to deal with this sort of situation? In brief - What's the best design pattern for a function which processes multiple things asynchronously, so that it ONLY calls back when all "things" have been completely processed? The simpler the better. Do I need to use some sort of queuing module like Q or node-queue?

Thanks much!

Edit: Something like this works inside the deepest loop in terms of not hitting the callback twice, but it seems like a kludge:

fs.readdir(path, function (err, files) {
        if(err) throw err;
        files.forEach(function(file) {
            fs.readFile(path+file, function(err, data) {
            if (err) throw err;    
            reports.push({ report: file, XML: data.toString()});  
            // WORKS, but seems hacky.   
            if (reports.length = files.length) callback(null, reports);
            });                           
        });
    });