1

I've node project. Root file is index.js and file helper.js, here I've some helper functions and it imported to index.js. I'm trying to get some data, using function in helper.js, but when I calling it in index.js it returning undefined. But in helper.js everething is OK, console.log showing data that I need. How I can fix this problem?

index.js file content:

const helper = require('./helper');

let data = helper.getData();
console.log(data); // undefined

helper.js file content:

const fs = require('fs');

module.exports = {
  getData: () => {
    fs.readFile('data.json', 'utf8', (err, data) => {
      const allData = JSON.parse(data);
      console.log(allData); // IS OK!
      return allData;
    });
  }
}

4 Answers4

5

You can use Promise:

const fs = require('fs');

module.exports = {
  getData: () => {
    return new Promise(function(resolve, reject){
        fs.readFile('data.json', 'utf8', (err, data) => {
            if(err){ 
                reject(err);
            } else {
                try {
                    resolve(JSON.parse(data));
                } catch(ex){
                    reject(ex);
                }
            }
        });  
    });
  }
}

and then:

helper.getData().then(function(data){
    console.log(data);
}, function(err){
    // here something failed
});

The problem is that fs.readFile method is asynchronous and will not give you as result any data check the documentation here.

So one option is to use a Promise as I did or to use a callback as suggested in the answer of @Tatsuyuki Ishi, you can check the docs about callback implementation.

codtex
  • 6,128
  • 2
  • 17
  • 34
  • 4
    Perfect well done for posting the code I was too lazy to write – Aron Apr 20 '17 at 10:49
  • I deleted my comment after your answer, was lazy to write a promise ;) – Tushar Gupta Apr 20 '17 at 10:50
  • I don't want to bother anyone, but IMHO this is a pretty bad answer, as it only suggests a solution, but does not explain with a single word what the underlying problem is. And, the shown solution is just an arbitrary one from a pool of more - why should I use a promise? I could also go with a callback, e.g. – Golo Roden Apr 20 '17 at 11:18
2

The problem is that fs.readFile is an asynchronous function and so doesn't return anything.

If you really need it to return something you can use the synchronous version, fs.readFileSync.

Otherwise - and a better way to do it - would be to have getData return a promise that you can then resolve with allData.

Aron
  • 8,696
  • 6
  • 33
  • 59
1

readFile is an asynchronous function, which accepts a callback. You have two options:

1 . Get a callback as parameter in getData().

  getData: (callback) => {
    fs.readFile('data.json', 'utf8', (err, data) => {
      const allData = JSON.parse(data);
      console.log(allData); // IS OK!
      callback(allData);
    });
  }

2 . Use the synchronous version.

  getData: () => {
    var data = fs.readFileSync('data.json', 'utf8');
    const allData = JSON.parse(data);
    console.log(allData); // IS OK!
    return allData;        
  }

Of course, you can use Promise which is more beautiful on chaining things, but it's often used with dependencies like Bluebird.

Tatsuyuki Ishi
  • 3,883
  • 3
  • 29
  • 41
1

The problem is, you are returning allData from the callback function, not the getData function. And since getData has no explicit return, your helper.getData() function will return undefined and this value would printed instead of what you wanted.

I suggest using Promise to return the data properly, as in @sand's answer.

serge1peshcoff
  • 4,342
  • 11
  • 45
  • 76