Stephane Karagulmez Stephane Karagulmez - 4 months ago 19
Javascript Question

Parsing Json after reading file with fs

I'm trying to establish communication between two node.js scripts.
The first one does a get request and write the response in a file.
The second watch the file after changes, then he read it, and prompt the result.

The first (get then write)

var request = require('request');
var parseString = require('xml2js').parseString;
var fs = require('fs');

//Some needed variables

streamInterval = setInterval(function() {
request.get(addr, function (error, response, body) {
if (!error && response.statusCode == 200) {
parseString(body,{ explicitArray : false, ignoreAttrs : true }, function (err, result) {
var jsonResult = JSON.stringify(result);
var result = JSON.parse(jsonResult);

fs.writeFile(outputDeparts, JSON.stringify(result, null, 4), function(err) {
if(err) {
console.log(err);
}
});

});
}else{
console.log("An error occured : " + response.statusCode);
}
}).auth(LOGIN,PASS,true);
}, 30000);


The second (watch after changes, read and prompt)

var fs = require('fs');

//Some needed variables


fs.watch(outputDeparts, (eventType, filename) => {
console.log(`event type is: ${eventType}`);
if (filename) {
console.log(`filename provided: ${filename}`);
fs.readFile(outputDeparts, 'utf8', function (err, data) {
if (err){
throw err;
}else{
console.log('start parsing');
console.log(data);
var result = JSON.parse(data);
var departs = result["passages"]["train"];
console.log(`next train [${departs[0]["num"]}] at : ${departs[0]["date"]}`);
}
});
} else {
console.log('filename not provided');
}
});


The first time the file is changed everything is ok ! But after 30 second, at the second change I get the following error :

undefined:1

SyntaxError: Unexpected end of input
at Object.parse (native)
at /Users/adobe/Documents/workspace/playWithNode/watchFile.js:17:23
at tryToString (fs.js:414:3)
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:401:12)


I thought it was a problem with reading/writting a file asynchronously but didn't manage to find a fix...
Is everyone able to help me or having clues ? Thanks

Answer

..it isn't encouraged to access the file system asynchronously because, while accessing, the target file can be modified by something in the App Life Cycle.

I suggest you to use fs.readFileSync and to wrap the JSON.parse in a try-catch

var fs = require('fs');

function onNextTrain(data) { 
  console.log("onNextTrain", data);
  
  return data;
}

fs.watch(outputDeparts, (eventType, filename) => {
  return new Promise((resolve, reject) => {
    if(!filename) {
      return reject("FILE NAME NOT PROVIDED");
    }
    
    let 
      data = fs.readFileSync(filename, 'utf8'),
      result
    ;
    
    try {
      result = JSON.parse(data);
    } catch(error) {
      result = data;
    }
    
    return resolve(result);
  })
    .then(onNextTrain)
    .catch(err => console.log("error", err))
  ;
});

Comments