JavaScript回调一个数组,其值通过循环推送

时间:2016-12-06 12:38:15

标签: javascript node.js express

我有一个带有Express.Js的Node.Js Web应用程序,它从xml文件中读取值,将所有xml文件中的值存储到一个数组中,子数组表示每个xml文件的分隔。目前,我在节点上有以下代码:

app.get('/get_software_requests', function (req, res) {
console.log("loading software requests");
requests_callback(function(all_software_requests){
    console.log(all_software_requests);
});

function requests_callback(callback){
    loadAllSoftwareRequests(function(all_software_requests){
    callback(all_software_requests);
    });
 }
});

function loadAllSoftwareRequests(callback){
console.log("loading requests");
fs.readdir("/project_requests", function(error, files) {
    files.forEach(filename => {
        var software_request = new Array();
        loadSoftwareRequestXML(filename, software_request, function(software_request){
            all_software_requests.push(software_request);
            callback(all_software_requests);
        });
    });
 });
}

function loadSoftwareRequestXML(filename, software_request, callback){
var xmlparser = new xml2js.Parser();
var filepath = "/project_requests/" + filename;
fs.readFile(filepath, "utf-8", function(error, values){
    xmlparser.parseString(values, function(error, xmlfile){
        var xmldata = xmlfile;
        date_requested = xmldata.ProjectRequest.DateRequested;
        client_org = xmldata.ProjectRequest.ClientOrganization;
        proposed_budget = xmldata.ProjectRequest.ProposedBudget;
        contact_name = xmldata.ProjectRequest.ContactName;
        delivery_date = xmldata.ProjectRequest.DeliveryDate;
        requirements = xmldata.ProjectRequest.UserRequirements;
        software_request.push(date_requested);
        software_request.push(client_org);
        callback(software_request);
    });
 });
}

到目前为止,对于“console.log(all_software_requests);”在主app.get上,控制台输出:

enter image description here

我希望Node只返回最后一次迭代结果,比如

enter image description here

感谢任何帮助或建议。请随意发表评论。感谢。

2 个答案:

答案 0 :(得分:0)

您可以使用原生承诺:

Promise.all(files.map(
    filename => new Promise(ok => load(filename, request => ok(request)))
)).then(requests => callback(requests));

我在这里搞乱了承诺/回调风格,以缩小您的代码版本 最好在客户端代码中使用promises而不是回调。

然后就变成了:

let loadAll = files => Promise.all(files.map(load));
let load = filename => {/*return some promise with result*/}

没有承诺,这并不太难:

let c = files.length; // initialize a counter
files.forEach(filename => {
    var software_request = new Array();
    loadSoftwareRequestXML(filename, software_request, function(software_request){
        all_software_requests.push(software_request);
        if(!--c) { // all async calls are finished
          callback(all_software_requests);
        }
    });
});

答案 1 :(得分:0)

您还可以添加我的“下一步”方法,为您处理循环。在这些类型的情况下,这对我很有用。

  app.get('/get_software_requests', function (req, res) {
    console.log("loading software requests");
    requests_callback(function(all_software_requests){
        console.log(all_software_requests);
    });

function requests_callback(callback){
    loadAllSoftwareRequests(function(all_software_requests){
    callback(all_software_requests);
    });
  }
});

function loadAllSoftwareRequests(callback){
console.log("loading requests");
fs.readdir("/project_requests", function(error, files) {
    files.forEach(filename => {
        var software_request = new Array();
        loadSoftwareRequestXML(filename, software_request, function(software_request){
            all_software_requests.push(software_request);
            callback(all_software_requests);
        });
    });
 });
}

function loadSoftwareRequestXML(filename, software_request, callback){
var xmlparser = new xml2js.Parser();
var filepath = "/project_requests/" + filename;
fs.readFile(filepath, "utf-8", function(error, values){
  var index = 0;
  var next = function () {
    if (index >= values.length) {
      callback(null, values);
      return;
    }
    var value = values[index];
    xmlparser.parseString(value, function(error, xmlfile){
      var xmldata = xmlfile;
      date_requested = xmldata.ProjectRequest.DateRequested;
      client_org = xmldata.ProjectRequest.ClientOrganization;
      proposed_budget = xmldata.ProjectRequest.ProposedBudget;
      contact_name = xmldata.ProjectRequest.ContactName;
      delivery_date = xmldata.ProjectRequest.DeliveryDate;
      requirements = xmldata.ProjectRequest.UserRequirements;
      software_request.push(date_requested);
      software_request.push(client_org);
      value.software_request = software_request;
      index++;
      next()
    });
  }
  next();
 });
}