我有一个带有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上,控制台输出:
我希望Node只返回最后一次迭代结果,比如
感谢任何帮助或建议。请随意发表评论。感谢。
答案 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();
});
}