在node.js应用程序中使用q.all的q.js实现并行异步性

Vie*_*van 4 node.js q

背景介绍:我编写了下面的代码来指示node.js:(1)从三个文本文件中组装一个HTML页面,其中我分别存储了pageheader,pagebody和pagefooter组件.显然,这些页面片段必须按正确的顺序组装.另一方面,完全没有要求必须在组装之前以任何顺序从文本文件中提取这些页面片段.我想通过实现并行异步性来利用它.

实施代码:

var sys = require('sys'),
http = require('http'),
fs = require('fs'),
Q = require('q'),
fullpage, pageheader, pagebody, pagefooter;

fullpage = '';

fs_readheader = fs.readFile('./htmlfiles.1', 'utf-8', function (err, data) {
   if (err) { throw err; }
   return pageheader = data;
});

fs_readbody = fs.readFile('./htmlfiles.2', 'utf-8', function (err, data) {
  if (err) { throw err; }
  return pagebody = data;
});

fs_readfooter = fs.readFile('./htmlfiles.3', 'utf-8', function (err, data) {
  if (err) { throw err; }
  return pagefooter = data;
});

finish = function(err, data) {
  if (err) { throw err; }
  console.log(pageheader);
  data = pageheader + pagebody + pagefooter;
  console.log(data);
  return fullpage = data;
}();


Q.all([fs_readheader,fs_readbody,fs_readfooter]).then(finish);


http.createServer(function(request, response) {
  response.writeHeader(200, {"Content-Type": "text/html"});
  response.write(fullpage);
  response.end();
}).listen(8001);
Run Code Online (Sandbox Code Playgroud)

问题:node.js服务器在127.0.0.1:8001处没有显示任何内容我当然希望HTML页面能够完整呈现.我正在使用q.js的1.00版本,这是q.js的最新版本.

后果:为了回应Barry-Johnson的全面意见,我将Barry-Johnson的代码修改为以下形式:

var http = require('http'),
  fs = require('fs'),
  Q = require('q');

var readFileP = Q.denodeify(fs.readFile);

http.createServer(function(request, response) {
  Q.all([ readFileP('./htmlfiles.1', 'utf-8'),
          readFileP('./htmlfiles.2', 'utf-8'),
          readFileP('./htmlfiles.3', 'utf-8') ])
    .done(function(content){
        response.writeHead(200, {"Content-Type": "text/html"});
        response.end(content.join(''));
    }); 

}).listen(8001);
Run Code Online (Sandbox Code Playgroud)

结果正是我想要的,一个完全组装的HTML页面 - 按正确的顺序.我将''作为参数添加到"join"方法中,因为我不希望这些部分用逗号连接.我使用了"完成"方法,因为我希望任何未捕获的错误都可以浮动.我理解,一般来说,我们不希望任何生产代码崩溃,Barry-Johnson实施"失败"方法就可以达到这个目的.

bar*_*son 8

SLaks在承诺方面是正确的.更一般地说,你要么有一个糟糕的复制/粘贴,要么承诺问题是你所经历的其他许多问题.让你的承诺在上面的代码中工作不会单独得到我相信你正在寻求的结果.

但是注重承诺-你需要看Q.denodeify,Q.ninvoke,Q.nfapply等见调整部分节点将q DOC的.这些调用允许您使用遵循具有尾随回调的标准节点约定的函数,而是将它们作为promise-returns函数进行操作.

这是个好消息 - 您需要处理的代码少得多.一些带有一些评论的版本留下了一些原始的冗长:

var sys = require('sys'),
    http = require('http'),
    fs = require('fs'),
    Q = require('q'),
    fullpage, pageheader, pagebody, pagefooter;

var readFileP = Q.denodeify(fs.readFile);

var fsReadheader = readFileP('./file1.html', 'utf-8');
var fsReadBody = readFileP('./file2.html', 'utf-8');
var fsReadFooter = readFileP('./file3.html', 'utf-8');

//  This is where you had Q.all before - which is probably not what you want,
// or did you want to just build the page once and have it static for the life
// of the app? If that is the case, promises are kind of pointless and you may
// as well K.I.S.S. and just read the bits synchronously at startup

http.createServer(function(request, response) {
    // you should probably wait to write out the response until you know if you have success.
    // but again, maybe you do want this to be totally static content
    response.writeHead(200, {"Content-Type": "text/html"});
    // I am assuming you wanted to load the files at request time, possibly
    // in preparation to adapting your code to make ti more dynamic.
    Q.all([fsReadheader,fsReadBody,fsReadFooter])
        .then(function (x) {
            // this was your old 'finish' function - doesn't really do much.
            // I used join instead of concatenating. less typing. And no typing
            // if you ever add file4
            return x.join();})
        .then(function(content){
            // You could response.write() as well, but you can send data with .end()
            response.end(content);
        })
        .fail(function(e){
            // here is where your error handler goes. any error will end up here.'
            // you could have more granular erro handling
            response.writeHead(500, 'Bad news, Tex');
            response.end('No dice');
        });
    //
}).listen(8001);
Run Code Online (Sandbox Code Playgroud)

但是,除非我通过按键获得报酬,否则我会这样写:

var http = require('http'),
    fs = require('fs'),
    Q = require('q');

var readFileP = Q.denodeify(fs.readFile);

http.createServer(function(request, response) {
    Q.all([ readFileP('./file1.html', 'utf-8'),
            readFileP('./file2.html', 'utf-8'),
            readFileP('./file3.html', 'utf-8') ])
        .then(function(content){
            response.writeHead(200, {"Content-Type": "text/html"});
            response.end(content.join());
        })
        .fail(function(e){
            response.writeHead(500, 'Bad news, Tex');
            response.end('No dice');
        });
    //
}).listen(8001);
Run Code Online (Sandbox Code Playgroud)

  • 非常欢迎你.如果解决方案满足您的需求,您可以接受答案.关于您的主要目标(具有动态页面内容的静态页眉/页脚) - 您可以查看[express.js](http://expressjs.com/),它支持Jade,EJS或其他类型的模板.或者使用上面的基本代码,对于真正的静态页眉/页脚,您只需在启动时将页眉和页脚加载到变量中,然后在请求时加载动态内容并将其与页眉/页脚变量连接.无论如何,祝它好运. (2认同)