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

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

执行代码:

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的代码修改为这种forms:

 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页面 – 以正确的顺序。 我将“'作为参数添加到”连接“方法,因为我不想用逗号连接这些部分。 我使用“完成”的方法,因为我想任何未被捕获的错误上浮。 我明白,一般来说,我们不希望任何生产代码崩溃,而巴里 – 约翰逊的“失败”方法的实施就是这样做的。

关于承诺SLaks是正确的。 更一般地说,你要么有一个不好的复制/粘贴,要么承诺的问题就是你所做的其他事情的次要问题。 在上面的代码中实现你的承诺并不是一个单一的结果,我相信你正在寻找。

但是关注承诺 – 您需要查看Q.denodeifyQ.ninvokeQ.nfapply等。请参阅Q文档的适配节点部分 。 这些调用使您可以使用符合标准节点约定的函数来处理尾随callback,而将其作为承诺返回函数进行操作。

这是一个好消息 – 你需要处理的代码less得多。 一些版本中有一些评论叶子在一些原始的冗长:

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