素材牛VIP会员
nodejs如何同步回调函数的执行?
 飘***子  分类:Node.js  人气:1177  回帖:3  发布于6年前 收藏
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,诸位轻喷。

 标签:node.js

讨论这个帖子(3)垃圾回帖将一律封号处理……

Lv1 新人
十***刻 产品经理 6年前#1

这个方案没有采用任何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');
Lv1 新人
陈***1 学生 6年前#2

并行读取,使用 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/');
Lv5 码农
超***侠 Web前端工程师 6年前#3

你需要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}
});
 文明上网,理性发言!   😉 阿里云幸运券,戳我领取