0

Need to parse some XML files from mass array with file_path values. Try to use async, fs, xml2js. When use single string file_path all works perfect. But when I use aync.filter() with array I can't understand how I can return result from xml.parseString()

const fs = require('fs');
const xml2js = require('xml2js');
const async = require('async');

var mass=['/file1.xml','/fil2.xml','/file3.xml',...]

async.filter(mass, async function(file_path, callback){
    if(fs.statSync(file_path)['size']>0){
        fs.readFileSync(file_path, 'utf8', function(err, data) {        
            xml.parseString(data, function (err, result) {
               console.log(Object.keys(result)[0]);
               return result; //need get this result to results array
            })
        }) 
    }
}, function(err, results) {
    console.log(results)
});

Who can understand how it works and what I need to change in my code. Thanks a lot!

Dan Mishin
  • 107
  • 2
  • 8

1 Answers1

0

You are trying to map and filter at the same time. Since your filter condition is synchronously available, use the array filter method for that, and then pass that to async.map.

You should then call the callback function, that async.map provides to you, passing it the result. So don't return it, but call the callback.

The readFileSync method does not take a callback like its asynchronous counterpart. It just returns the data.

Also, drop the async keyword, as you are not using the await keyword at all.

async.map(mass.filter((file_path) => fs.statSync(file_path).size > 0), 
    function(file_path, callback){
        var data = fs.readFileSync(file_path, 'utf8');
        xml.parseString(data, function (err, result) {
           console.log(Object.keys(result)[0]);
           callback(null, result);
        }) 
    }, function(err, results) {
        console.log(results)
    }); 

It should be noted however, that since Node now comes with the Promise API, and even the async/await extension to that, the async module has become much less interesting. Consider using Promises.

const promises = mass.filter(file_path => {
    return fs.statSync(file_path).size > 0
}).map(function(file_path) {
    return new Promise(resolve => {
        const data = fs.readFileSync(file_path, 'utf8');
        xml.parseString(data, function (err, result) {
            console.log(Object.keys(result)[0]);
            resolve(result);
        });
    }); 
});
Promise.all(promises).then(results => {
    console.log(results);
}); 
trincot
  • 317,000
  • 35
  • 244
  • 286
  • unfortunately `results` is `undefined`. I try to understand Promise API on your example . Thanks! – Dan Mishin Mar 17 '19 at 14:23
  • `console.log(Object.keys(result)[0]);` works fine. But how I can push `result` from parse to `results` array of filter/map function – Dan Mishin Mar 17 '19 at 14:27
  • Corrected a mistake (`asyc.filter` should be `async.map` and callback should pass a null value) and added a Promise version. – trincot Mar 17 '19 at 14:56
  • It's work great with promises! I really need to learn Promise methods! Thank you so much @trinton! – Dan Mishin Mar 17 '19 at 15:20