Max Max - 6 months ago 23
Javascript Question

Callback function that returns data - make it anonymous, a function or a module?

I wrote this little function in JavaScript:

var getChampionFile = function(callback){
var championFile = JSON.parse(fs.readFileSync(
'dragontail/championFull.json',
'utf8'
));
return callback(championFile);
};


I made a callback for obvious reasons. So when I use the
getChampionFile
function, I pass in an anonymous function as a callback that simply returns the
championFile
.

EDIT: as pointed out, the callback was not obvious. I used
fs.readFile
instead of
fs.readFileSync
when writing the callback, I didn't notice I had changed it somewhere along the way (maybe I took it over from the internet, maybe Atom suggested it and I accidentally used it) - sorry for any confusion.


var getAllChampions = function(){
var championFile = getChampionFile(function (championFile){
return championFile;
});
return championFile.data;
};


Now I want to write some more functions that use this
getChampionFile
function. I have the following options:


  • Write that anonymous function every time again

  • Turn the anonymous function into a separate re-usable function, eg.
    var returnData = function(data){return data;}
    and put that in a seperate module so I can use it everywhere in my project, but requiring a module for a function that's 1 line of code just seems silly.

  • Make a function that doesn't need a callback, invokes
    getChampionFile()
    and passes the anonymous function as a callback. (basically
    getAllChampions()
    with
    return championFile;
    instead of
    return championFile.data;
    )



What would be the recommended option / best practice?

Answer Source

You have a misunderstanding in a comment here which has kind of taken you down the rabbit hole:

To make sure the .json file is read before handling it, I thought it was necessary to implement a callback.

It is, if you're reading it asynchronously. But you're not, you're using readFileSync.

Reading it asynchronously would be much better; synchronous I/O is a major no-no on NodeJS.

Instead, read the file asynchronously and either provide a Node-style callback parameter:

var getChampionFile = function(callback) {
    fs.readFile('dragontail/championFull.json', 'utf8', function(err, data) {
        if (err) {
            callback(err);
        } else {
            try {
                callback(null, JSON.parse(data));
            } catch (e) {
                callback(e);
            }
        }
    ));
};

...or create a Promise-enabled function instead:

var getChampionFile = function() {
    return new Promise(function(resolve, reject) {
        fs.readFile('dragontail/championFull.json', 'utf8', function(err, data) {
            if (err) {
                reject(err);
            } else {
                try {
                    resolve(JSON.parse(data));
                } catch (e) {
                    reject(e);
                }
            }
        ));
    });
};

Then, compose the function just like you compose other Node-style callback functions, or other Promise-enabled functions, depending on which way you go.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download