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

在node.js应用程序中使用q.all of q.js实现并行异步,node.js,q,Node.js,Q,背景简介:我编写了下面的代码来指示node.js:(1)从三个文本文件中组装一个HTML页面,其中分别存储了pageheader、pagebody和pagefooter组件。显然,这些页面片段必须按照正确的顺序进行组装。另一方面,根本不要求在组装这些页面片段之前,必须以任何顺序从其文本文件中提取这些页面片段。我想通过实现并行异步性来利用这一点 实施代码: var sys = require('sys'), http = require('http'), fs = require('fs'), 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);
问题是: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);

结果正是我想要的,一个完全组装好的HTML页面——顺序正确。我将“”作为参数添加到“join”方法中,因为我不希望用逗号连接各个部分。我使用“done”方法是因为我想让任何未捕获的错误浮起。我明白,一般来说,我们不希望任何生产代码崩溃,Barry Johnson实现的“fail”方法也可以达到这个目的。

SLaks关于承诺是正确的。更一般地说,你要么有一个坏的复制/粘贴,要么承诺的问题是次要的,你有这么多的其他事情。在上面的代码中实现你的承诺并不能单独得到我相信你正在寻求的结果

但是,关注承诺-您需要查看
Q.denodeify
Q.ninvoke
Q.nfapply
等。请参阅Q文档的。这些调用允许您使用遵循标准节点约定的函数,即具有尾部回调,并将它们作为承诺返回函数进行操作

好消息是,您需要处理的代码要少得多。带有一些注释的版本保留了一些原始的详细内容:

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);
但是,除非我通过击键获得报酬,否则我会这样写:

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

承诺回调不接受错误参数。@Slaks-您是对的,因为承诺链旨在准确地复制回调链,但附带条件是错误将移动到承诺链的最后一个链接,即“完成”或“失败”,在该链接中进行处理。在承诺链的最后一个链接或节点中处理错误的要求意味着,任何作为承诺链一部分的类似节点的函数——在将其放入承诺链之前,该类似节点的函数必须“promisified”,并从中取出错误元素。链的最后一个环节中的功能尚未实现。感谢您的全面输入。我进一步简化了代码。代码背后的想法是,我将把HTML页面放在一起,这些页面的页眉和页脚是静态的,内容是任意和动态的。我对承诺是新的,这是显而易见的,我对承诺的承诺感到兴奋:)非常欢迎。如果解决方案满足了您的需求,您可以接受答案。关于您的主要目标(带有动态页面内容的静态页眉/页脚)-您可以查看它对Jade、EJS或其他类型模板的支持。或者使用上述基本代码,对于真正的静态页眉/页脚,只需在启动时将页眉和页脚加载到变量中,然后在请求时加载动态内容,并将其与页眉/页脚变量连接起来。无论如何祝你好运。