node.js回调多个函数

时间:2014-03-25 14:07:30

标签: javascript node.js callback

我一直在努力解决这个问题已经有一个星期了,我已经阅读了几十篇关于回调的文章和帖子,其中一些一遍又一遍。我仍然不明白 - 至少我正在努力做什么。

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);

我在getRtn()中有来自fs.readfile的结果,但我无法设计一个回调方案来将相同的结果输入到sendPage()中,并可能返回到requestHandler()。

sendPage()会做很多事情,但它会成为许多不同事物的集合点。

我已经尝试了25次将回调插入到getRtn()中,但是它出现“意外功能”错误,即使没有错误,我也不知道......我只是不知道。即使在fs.read中运行的一个回调中,我也不知道是谁在调用谁。

但最后,sendpage将收集来自十几个不同函数的所有结果,其中一些函数可能来自几个函数,因此结果将通过许多函数遍历许多回调。

如果有人能告诉我如何继续从我在getRtn中看到的结果回调,一直回到requestHandler()(或者至少回到sendPage(),我将永远感激。

2 个答案:

答案 0 :(得分: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!'

答案 1 :(得分:0)

我认为你不需要这么多层功能......用匿名函数完成,代码可能看起来像这样......

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);

每次回调实际上只是等待某事发生。它只是让节点在等待时执行summat else ...一个问题是与作用域有关... res需要在readfile回调的范围内才能写入它。我编写它的方式会创建一个闭包,因此回调仍然可以访问外部作用域中的变量。如果你想分离这些函数,你必须在requestHander中定义回调 以获得正确的闭包:

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
}

我认为第一种方式更具可读性。 : - )

它的工作方式是:

  • 请求进入并调用其回调。

  • 该回调(requestHandler)设置了读取并移交回调...

  • ...一旦提取了文件就会启动,并完成发送响应的处理。

所以,这是一个普遍的答案。但在这种情况下,有一种更简单的方法,使用.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);