0

I'm writing an electron app that requires me to read from a file and parse its contents into a javascript object using jQuery, and I've been having trouble. At the moment myObject (see in code) is returning null, when it should be returning a live javascript object parsed from the json file. The code I'm using is below and may be worth pointing out that it is written in a renderer process. I'm pretty new to javascript so it could well be something obvious I'm missing.

loadObjectBtn.addEventListener('click', function loadObject(event){

    myObject = jsonParser('C:\\someFolder\\myApp\\myJsonFile.json')
    console.log(myObject)
    return myObject
})

function jsonParser(fileName){

    var jsonObj = null
    fs.readFile(fileName, 'utf8', function (err,data){
        if(err){
            return console.log(err)
        }
        console.log("read from file successfully")
        jsonObj = jQuery.parseJSON(data)
    }) 
    return jsonObj
}

Interestingly if I run the code with a break point on the line:

return jsonObj

in the function jsonParser(), the code seems to work and returns a proper value for myObject. Do any of you guys know why this might be, or have a suggestion for some alternative code?

Thanks for reading!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

2 Answers2

0

fs.readFile is an asynchronous function. What that means is, at the time your jsonParser executes and return jsonObj; is executed, it has not yet been initialized (this will happen later asynchronously when your callback to fs.readFile is invoked). That is why it is undefined

You can modify your jsonParser function to accept a callback which you can use to hand the parsed data back after it is done to your main function.

Sample:

loadObjectBtn.addEventListener('click', function loadObject(event){

    jsonParser('C:\\someFolder\\myApp\\myJsonFile.json',function(err, data){
        //Check for error
        if(err){
            // Handle error
            return;
        }
        // Data is available here
        console.log(data)
    })

})

function jsonParser(fileName, cb){
    cb = (cb && typeof cb === 'function' && cb) || function(){};
    fs.readFile(fileName, 'utf8', function (err,data){
        if(err){
            // Error happened, call the cb function with the error as first argument
            cb(err)
        }
        //It worked, parse and hand the data back to the callback
        var jsonObj = jQuery.parseJSON(data)
        cb(null,jsonObj);
    }) 
}

Handy link on understanding error first callbacks

EDIT: Adding link shared by @Archer in the comments Asynchronous vs synchronous execution, what does it really mean?

An alternative (though generally discouraged) is to use the synchronous version fs.readFileSync

Related Question on readFile vs readFileSync

Chirag Ravindra
  • 4,760
  • 1
  • 24
  • 35
0

This is because fs.readFile is asynchronous, it will take some time before the data is available. That is why we pass a call back function to all async calls. Here is a small rewrite:

loadObjectBtn.addEventListener('click', function loadObject(event){
    jsonParser('C:\\someFolder\\myApp\\myJsonFile.json', printJSON)
})

function printJSON (jsonData) {
    console.log("read from file successfully");
    jsonObj = jQuery.parseJSON(jsonData);
    console.log(jsonObj);
}

function jsonParser(fileName, callback){
    var jsonObj = null;
    fs.readFile(fileName, 'utf8', function (err,data){
        if(err){
            return console.log(err)
        }
        return callback(data)
    })
}
surajck
  • 1,186
  • 9
  • 23