I have a Node.Js web app with Express.Js that reads values from xml files, store values from all xml files into an array with sub-array represent the separation of per xml file. At the moment, I have the following code on the Node:
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);
});
});
}
So far, for "console.log(all_software_requests);" on the main app.get, the console outputs:
I want the Node to only return the last iteration result, like
Any help or suggestion is appreciated. Please feel free to comment. Thanks.
You can use native promises for that:
Promise.all(files.map(
filename => new Promise(ok => load(filename, request => ok(request)))
)).then(requests => callback(requests));
I mess with promise/callback style here to minify your code editions.
Better to use promises instead of callbacks in client code too.
Then it becomes just:
let loadAll = files => Promise.all(files.map(load));
let load = filename => {/*return some promise with result*/}
Without promises at all it is not too difficult:
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);
}
});
});
You could also add my "next" method that will handle the looping for you. This has worked well for me in these types of situations.
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();
});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.