Adrian Gherasim
Adrian Gherasim

Reputation: 135

Promises in NodeJS

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

Answers (1)

clay
clay

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

Related Questions