NodeJS中的承诺
问题描述:
我正试图在NodeJS中使用Bluebird或Q将某些回调转换为Promise,但是我没有成功。 任何人都可以很好,给我一个例子如何将上面的代码转换为承诺?NodeJS中的承诺
在此先感谢
阿德里安
function httpResponse(request, response) {
fs.readFile('views/main.ejs', 'utf-8', function readFile(error, file) {
if (error) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write('EJS ERROR');
response.end();
} else {
// get domains data from db needed for main page
dbHandle.queryDB({}, "domains", function dbQueryDB(error, result) {
var ejsData = {name: "Cav"};
if (error) {
response.write('DB ERROR');
response.end();
} else {
ejsData.domains = result;
// get machine type data from db needed for main page
dbHandle.queryDB({}, "type", function dbQueryDB(error, result) {
if (error) {
response.write('DB ERROR');
response.end();
} else {
ejsData.type = result;
//respond index.html
response.writeHead(200, {"Content-Type": "text/html"});
response.end(ejs.render(file, ejsData));
}
});
}
});
}
});
}
答
使用bluebird
,看看在promisification section。
基本上你会做这样的事情:
var fs = require("fs");
Promise.promisifyAll(fs);
Promise.promisifyAll(dbHandle); //do this globally if it is global, not every request!
那么你的代码将是这样的:
function httpResponse(request, response) {
fs.readFileAsync('views/main.ejs', 'utf-8')
//Special catch only for EJS errors. ONce past this point in the chain, will not hit again.
.then(function(file){
return dbHandle.queryDBAsync({}, "domains");
})
.then(function(domains){
ejsData.domains = domains;
return dbHandle.queryDBAsync({}, "type");
})
.then(function(types){
ejsData.type = types;
response.writeHead(200, {"Content-Type": "text/html"});
response.end(ejs.render(file, ejsData));
})
.catch(function(error){
response.writeHead(200, {"Content-Type": "text/plain"});
response.write('EJS ERROR'); //or DB errors, add some handling if the error message is important
response.end();
});
}
我这些链接一起保持代码更加平坦。你也可以嵌套承诺。但Promisification是与这里建立图书馆的途径。
编辑 要保持file
在范围内,请尝试像这样的Promise设置。请注意嵌套的Promise。
function httpResponse(request, response) {
fs.readFileAsync('views/main.ejs', 'utf-8')
//Special catch only for EJS errors. ONce past this point in the chain, will not hit again.
.then(function(file){
return dbHandle.queryDBAsync({}, "domains")
.then(function(domains){
ejsData.domains = domains;
return dbHandle.queryDBAsync({}, "type");
})
.then(function(types){
ejsData.type = types;
response.writeHead(200, {"Content-Type": "text/html"});
response.end(ejs.render(file, ejsData));
})
.catch(function(error){
response.writeHead(200, {"Content-Type": "text/plain"});
response.write('EJS ERROR'); //or DB errors, add some handling if the error message is important
response.end();
});
}
另一种方法是追踪Promise链外的file
变量。当返回readFileAsync
时,将result
存储为file
(您宣布不在该独家新闻中),然后您可以稍后使用它。
感谢您的快速回答。 –
顺便说一下,我在“response.end(ejs.render(file,ejsData));”得到了“文件未定义”。我想这是因为这不是一个闭包,因为它不能看到文件变量。 –
啊,这就是像这样的链接承诺 - '.then()'变量超出范围。我会为你编辑我的答案,以展示如何减少嵌套,但保持范围。 – clay