优化设计模式 - 处理多个文件的功能

时间:2014-08-18 22:51:08

标签: node.js asynchronous

目标是创建不同的函数,分离加载多个(xml)文件并解析它们的工作。我可以在一个函数中完成所有操作,但嵌套的回调开始变得丑陋。换句话说,我想要这样做:

// 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!
                    });
                 });
             });                           
       });
});

相反,我想要一个函数来读取我的文件并将每个文件的XML有效负载放入一个对象数组中,然后返回给调用者(每个对象代表文件的名称和文件中的XML) 。这是可能将报告加载到数组中的函数:

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);
    });

}

...这里的功能将调用上面的那个:

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     
        } );  
}

正如您在loadReports()注释中看到的那样,我无法使回调正常工作。它要么在数组完全填充之前回调,要么回调两次 - 每次fs.readFile操作一次。

那么......处理这种情况的最佳方法是什么?简而言之 - 对于一个异步处理多个事物的函数来说,最好的设计模式是什么,所以它只能在所有"事物"已经完全处理?越简越好。我是否需要使用某种排队模块,如Q或node-queue?

非常感谢!

编辑:这样的事情在最深的循环中起作用,没有两次回击,但它看起来像一个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);
            });                           
        });
    });

0 个答案:

没有答案