Reputation: 135
I'm trying to convert some callback to Promises in NodeJS using Bluebird or Q but I didn't success. Can anyone be nice and give me an example how can I convert the above code to Promises?
Thanks in advance
Adrian
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));
}
});
}
});
}
});
}
Upvotes: 1
Views: 560
Reputation: 6017
Using bluebird
, have a look at the promisification section.
Basically you'd do something like:
var fs = require("fs");
Promise.promisifyAll(fs);
Promise.promisifyAll(dbHandle); //do this globally if it is global, not every request!
Then your code would be something like:
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();
});
}
I chained these all together to keep the code more flat. You could nest the promises as well. But Promisification is the way to go here with establish libraries.
Edit
To keep file
in scope, try a Promise setup like this. Note the nested 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();
});
}
An alternative to that is to track the file
variable outside the Promise chain. When readFileAsync
is returned, store the result
to file
(that you declared out of the scoop), and you can use it a few steps later.
Upvotes: 1