0

I've been struggling with this for a week now, and I have read dozens upon dozens of articles and posts related to callbacks, some of them over and over again. I still do not understand - at least for what I'm trying to do.

function rFile(dIn, callback){  // 4.
    fs.readFile(dIn,function(err,dOut){
        if(!err){
            console.log('rFile OUT: '+dOut+' B Size: '+dOut.length);
        } else {
            console.log('rFile ERR: '+err);
        };
        callback(dOut);
    });
}


function getRtn(dOut){  // 3.
    console.log('getRtn OUT: '+dOut);
    rtn = dOut;
    return dOut;
};


function sendPage() {  // 2.
    rFile('index.htm', getRtn);
    console.log('sendPage OUT: '+rtn);
    rFile('404.htm', getRtn);
    console.log('sendPage OUT: '+rtn);

}

function requestHandler(req, res) {  // 1.
    sendPage();
    res.end();
    console.log('sendPage OUT: '+rtn);
}

http.createServer(requestHandler).listen(3000);

I have the results from fs.readfile in getRtn(), but I cannot devise a callback scheme to get that same result into sendPage(), and possibly back to requestHandler().

sendPage() is going to do quite a few things, but it will be a collection point for a bunch of different things.

I've tried probably 25 times to insert a callback into getRtn(), but it errors with "unexpected function", and even if there was no error, I would't know... I just don't know. Even in the one callback that works inside fs.read, I don't know who is calling who.

But in the end, sendpage will gather all the results from a dozen different functions, some called from probably several functions deep, so the results will traverse many callbacks through many functions.

If anyone can show my how to continue calling back from the results I see in getRtn, all the way back to requestHandler() (or at least back to sendPage(), I'd be forever grateful.

2 Answers 2

1

Something like this perhaps?

function rFile(callback) {
  console.log('rFile called');
  callback('rFile');
}

function getRtn(callback) {
  console.log('getRtn called');
  callback('Returned data!');
}

function sendPage() {
  rFile(function (rFile) {
    getRtn(function (data) {
      console.log(rFile, data);
      // do what you like with the data here.
    });
  });
}

sendPage(); // console: 'rFile called', 'getRtn called', 'rFile', 'Returned data!'
Sign up to request clarification or add additional context in comments.

2 Comments

I still don't see how my rFile data is getting back to sendPage.
@edasac, how about now?
0

I think you don't need so many layers of function... done with anonymous functions, the code might look like this...

var http = require('http');
var fs = require('fs');

function requestHandler(req, res) {
    console.log('Request received: '+req.url);
    res.setHeader("Content-Type", "text/html");
    fs.readFile("index.htm", function(err, data ) {
        if (err) throw err;
        console.log('sending page out:\n' + data);
        res.end(data);
    });
}

http.createServer(requestHandler).listen(3000);

Each callback is effectively just a wait for something to happen. It just lets node do summat else whilst waiting... One catch is to do with scopes... res needs to be in scope for the readfile callback to be able to write to it. The way I've written it creates a closure, so the callback still has access to the variable in the outer scope. If you wanted to separate the functions, you'd have to define the callback inside the requestHander to get the right closure:

function requestHandler(req, res) {
    function rfCallback(err, data ){
        if (err) {console.log('Readfile Err');throw err;}
        res.end(data);
        console.log('sendPage OUT:\n'+ data);
    }
    console.log('Request received: '+req.url);
    res.setHeader("Content-Type", "text/html");
    fs.readFile("index.htm", rfCallback); //set up the read & send
}

I think the first way is more readable. :-)

The way it works is:

  • The request comes in and calls its callback.

  • That callback (requestHandler) sets up the read and hands off to its callback...

  • ...which kicks off once the file has been fetched, and finishes dealing with sending the response.

So, that's a general answer. But in this case, there's an easier way, using .pipe():

var http = require('http');
var fs = require('fs');

function requestHandler(req, res) {
    console.log('Request received: '+req.url);
    res.setHeader("Content-Type", "text/html");
    fs.createReadStream("index.htm").pipe(res); //set up the read & send
}

http.createServer(requestHandler).listen(3000);

7 Comments

Kim, thank you. I understand how you feel I have too many functions. But for example: From sendPage(), I will read 3 files to build one inside of sendpage(), and get that back to requestHandler() to write out (plus I want to do alittle buffer exercise in sendPage()). Additionly, I intend for sendPage() to do more (like possibly child processes), unless I should use requestHandler() for the bulk of my logic.
.pipe() has an option to not send the end, if you want to pipe several files: fs.createReadStream("index.htm").pipe(res, {end: false});. Just use the default for your last file.
Node doesn't have the concept of child processes -- it's aggressively single-threaded; everything is handled in its event loop. So, if you want to "do stuff" in a function, fine, but in the end you have to have a program flow from one callback to another. The thing that sets up the action which will create an event later to trigger its callback will be long gone by the time the callback actually happens. There's no concept of "going back" to the thing that set up the callback. Not sure if that makes it any clearer?
Thank you Kim! This will give me something to chew on for a bit.
"There's no concept of "going back" to the thing that set up the callback." I am struggling with that concept ( or lack there of) to say the least. Although, I'm really just starting w/ node, so my whole overall concpet of what I'd like to do is probably very broken.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.