搜索

首页  >  问答  >  正文

node.js - nodejs如何同步回调函数的执行?

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

http.createServer(function (req, res) {

    res.writeHead(200, {'Content-Type': 'text/plain'});
    fs.readFile('a.txt', function(err, data){
        res.write(data);
        fs.readFile('b.txt', function(err, data){
            res.end(data);
        });
    });

}).listen(1337, '127.0.0.1');

console.log('Server running at http://127.0.0.1:1337/');

http接受用户请求时会合并目录下a.txt和b.txt文件的内容进行返回,并且要保证a.txt的内容在b.txt之前,上面的代码通过嵌套回调函数可以实现这一效果。

但是这样的嵌套使得文件打开是串行的,不可能要合并多少个文件就嵌套多少层(简直疯了),嵌套不仅慢而且乱。听说有基于事件的模块可以使文件并行同步打开,然后一起返回,但是我找官方的API没找到。

鄙人才接触Nodejs,诸位轻喷。

PHPzPHPz2782 天前599

全部回复(3)我来回复

  • 高洛峰

    高洛峰2017-04-17 11:06:36

    并行读取,使用 EventProxy 的话:

    var http = require('http');
    var fs = require('fs');
    var EventProxy = require('eventproxy');
    
    http.createServer(function (req, res) {
    
        res.writeHead(200, {'Content-Type': 'text/plain'});
    
        var ep = new EventProxy();
    
        fs.readFile('a.txt', ep.done('a'));
        fs.readFile('b.txt', ep.done('b'));
    
        ep.all('a', 'b', function (a, b) {
            res.write(a);
            res.write(b);
            res.end();
        });
    
        ep.once('error', function (err) {
            // 别忘了异常处理
        });
    
    }).listen(1337, '127.0.0.1');
    
    console.log('Server running at http://127.0.0.1:1337/');
    

    回复
    0
  • 黄舟

    黄舟2017-04-17 11:06:36

    你需要async https://github.com/caolan/async

    比如,下面的例子,是并行执行one,two,完了之后调用最后的函数
    使用paraller函数
    parallel(tasks, [callback]) (多个函数并行执行)

    // an example using an object instead of an array
    async.parallel({
        one: function(callback){
            setTimeout(function(){
                callback(null, 1);
            }, 200);
        },
        two: function(callback){
            setTimeout(function(){
                callback(null, 2);
            }, 100);
        }
    },
    function(err, results) {
        // results is now equals to: {one: 1, two: 2}
    });
    

    回复
    0
  • 怪我咯

    怪我咯2017-04-17 11:06:36

    这个方案没有采用任何js库,方法也不算很难

    var http = require('http');
    var fs = require('fs');
    
    http.createServer(function (req, res) {
        if(req.url!='/')return res.end();
        res.writeHead(200, {'Content-Type': 'text/plain'});
        //新建一个任务队列
        var query=[];
    
        //将需要执行的任务加入到队列中
        ['main.c','server.js'].forEach(function(filename){
            query.push(function(next){
                    fs.readFile(filename,function(err,data){
                        //出现错误时将err加入至next里
                        if(err)return next(err);
                        res.write(data);
    
                         //进行下一个任务。
                        next();
                    })
    
            })
        })
    
        //给队列加入一个函数,当队列运行结束时会执行它,这里可以有更好的做法
        query.end=function(err){
            res.end(err);
        };
    
        //根据index运行队列中的任务,如果index未指定,则从第一个任务开始运行
        function startQuery(query,index){
            var index=index||0;
    
            //如果到达队列尾部,则调用end
            if(index>=query.length){
                query.end();
                return;
            };
    
            //提取并执行任务
            var task=query[index];
            task(function(err){
                //调用next会执行到这里,如果任务返回了err,则结束队列执行end
                if(err){
                    query.end(err);
                    return;
                }
                else{
                    //没有返回err,则执行下一个任务
                    startQuery(query,++index);
                }
            })
        }
    
        //开始执行第一个任务
        startQuery(query);
    
    }).listen(1337, '127.0.0.1');
    
    console.log('Server running at http://127.0.0.1:1337');
    

    回复
    0
  • 取消回复