0

If I have the following code:

var content;
var f = fs.readFile('./index.html', function read(err, data) {
    if (err) {
        throw err;
    }
    content = data;
    return console.log(content);
});

f();

I got the following:

f();
^
TypeError: undefined is not a function

How can I do to return a function, which is not undefined?

My real issue, in a bigger context is the following https://gist.github.com/jrm2k6/5962230

Jeremy D
  • 4,787
  • 1
  • 31
  • 38
  • You don't, you need to perform the actions _inside_ the readFile callback - or wrap it in a function that accepts a callback itself. See [this similar post](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call/16825593#16825593) on how to return from an AJAX call. – Benjamin Gruenbaum Jul 09 '13 at 23:00
  • @BenjaminGruenbaum Well, `f` *could* be a function. However, `fs.readFile()` does not return one. – Jonathan Lonowski Jul 09 '13 at 23:34

2 Answers2

3

You can't usefully return from within the callback to your code.

  1. Using return inside the callback doesn't return a value to your code. fs.readFile() calls the callback itself so the return value is given to it. For your code to receive it, fs.readFile() would have to return the value it got from the callback, which it doesn't.

  2. And, since fs.readFile() is asynchronous, it actually can't. Your code spans 2 different points in time:

    1. "Present"

      var content;
      var f = fs.readFile('./index.html', /* ... */);
      
      f();
      
    2. "Future"

      /* ... */
      function read(err, data) {
          if (err) {
              throw err;
          }
          content = data;
          return console.log(content);
      }
      /* ... */
      

You simply can't use a value from the "Future" in the "Present" -- or, at that point, the "Past."

This all generally leads to continuing the callback pattern rather than using return. Taking your "real" code:

var cheerioURLContent = function (url, callback) {
    rest.get(url).on("complete", function (result) {
        callback(cheerio.load(result));
    });
};

cheerioURLContent('./index.html', function (t) {
    console.log(t);
});
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
  • Ok, and what if I need to assign this function cheerioURLContent to a variable, which has to be a function? I have to delay this assignment right? – Jeremy D Jul 09 '13 at 23:59
  • @JeremyD The issue is in trying to set `var t = cheerio.load(result);` before there's actually a `result`. Just as `fs.readFile()` couldn't `return` a value from the callback, neither can `cheerioURLContent` nor `rest.get()`. – Jonathan Lonowski Jul 10 '13 at 00:01
1

You can assign event handlers for custom events and trigger (emit) the events from within the callback. It's a bit hard to get your head around at first, but pretty elegant.

See Emitting event in Node.js for an example.

Community
  • 1
  • 1
Pete Scott
  • 1,516
  • 10
  • 10