Frage

So.. I'm having the hardest time learning how to Promise.

I'm using bluebird (https://github.com/petkaantonov/bluebird) as suggested to me -- in order to tame my callback hell I've been getting. Example:

function login(req,res,con,mysql,P) {
var ref = undefined;
    con.getConnection(function(err,connection) {
        if (err) console.log("Get Connection Error.. "+err);
        con.query('SELECT password,id FROM player WHERE name='+mysql.escape(req.body.user),function(err,rows,fields) {
            if (err) throw err;
            if (!rows[0]) {
                res.send({
                    "msg":"Your username and or password was incorrect.",
                    "flag":true,
                    "title":": Login Failed"
                });
            }
            if (rows[0].password !== "undefined") {
                if (hash.verify(req.body.pass,rows[0].password)) {
                    req.session.loggedIn = true;
                    req.session.user = rows[0].id;
                    ref = new P(rows[0].id,con,req);
                    res.send({
                        "msg":"You have logged in!",
                        "flag":false,
                        "title":": Logged In"
                    });
                } else {
                    res.send({
                        "msg":"Your username and or password was incorrect.",
                        "flag":true,
                        "title":": Login Failed"
                    });
                }
            }
        });
        connection.release();
    });
    console.log(ref);
    return ref;
}

It's nasty, it's full of callbacks, and the function returns ref before the query callback is finished executing.

Solution: promises!

I tried to convert my function using the quick start.. so I promisefyAll'd my mysql module before creating the connection:

var mysql = require("mysql");
var Promise = require("bluebird");
Promise.promisifyAll(mysql);

And I wrote my function as follows:

function login(req,res,con,mysql,P) {
    var ref = undefined;
    Promise.promisify(con.getConnection)().then(function(connection) { //updated line returns error no method promisify. Bluebird v. 1.1.1
        con.query('SELECT password,id FROM player WHERE name='+mysql.escape(req.body.user)).then(function(rows,fields) {
            if (hash.verify(req.body.pass,rows[0].password)) {
                req.session.loggedIn = true;
                req.session.user = rows[0].id;
                ref = new P(rows[0].id,con,req);
                res.send({
                    "msg":"You have logged in!",
                    "flag":false,
                    "title":": Logged In"
                });
            } else {
                res.send({
                    "msg":"Your username and or password was incorrect.",
                    "flag":true,
                    "title":": Login Failed"
                });
            }
        });
        return ref;
    });
}

But I keep getting TypeError: Cannot call method 'then' of undefined at Object.login (/var/www/post/posts.js:36:22)

And

TypeError: undefined is not a function at Pool.<anonymous> (/var/www/node_modules/mysql/lib/Pool.js:53:14)

Errors. Can somebody help me understand how to implement promises for querying my database (correctly)?

Edit (post answer acceptance:): here is how I call the login function:

app.post("/login",function(req,res) {
    Player = post.login(req,res,con,mysql,p);
    console.log(Player); // logs [Object object]
}); //inside the login function, it logs the object like it should
War es hilfreich?

Lösung

When you promisify a prototype, the promise returning methods will have *Async suffix

The idea of promisification is to pretend as if the library was designed to return promises to begin with. You should not call promisify in application code during runtime, but in your appliation bootstrap init code or similar.

var mysql = require("mysql");
var Promise = require("bluebird");
//Only need to be called once per application so probably not here
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);

function login(req,res,con,mysql,P) {
    return con.getConnectionAsync().then(function(connection) {
        return connection.queryAsync('SELECT password,id FROM player WHERE name='+
               mysql.escape(req.body.user)).spread(function(rows, fields) {
            if (hash.verify(req.body.pass,rows[0].password)) {
                req.session.loggedIn = true;
                req.session.user = rows[0].id;
                var ref = new P(rows[0].id,con,req);
                res.send({
                    "msg":"You have logged in!",
                    "flag":false,
                    "title":": Logged In"
                });
                return ref;
            } else {
                res.send({
                    "msg":"Your username and or password was incorrect.",
                    "flag":true,
                    "title":": Login Failed"
                });
            }
        }).finally(function() {
            connection.release();
        });
    });
}

A future version will have much better resource management and you will be able to do:

function login(req,res,con,mysql,P) {
    return Promise.using(con.getConnectionAsync(), function(connection) {
        return connection.queryAsync('SELECT password,id FROM player WHERE name='+
               mysql.escape(req.body.user));
    }).spread(function(rows, fields) {
        if (hash.verify(req.body.pass,rows[0].password)) {
            req.session.loggedIn = true;
            req.session.user = rows[0].id;
            var ref = new P(rows[0].id,con,req);
            res.send({
                "msg":"You have logged in!",
                "flag":false,
                "title":": Logged In"
            });
            return ref;
        } else {
            res.send({
                "msg":"Your username and or password was incorrect.",
                "flag":true,
                "title":": Login Failed"
            });
        }
    });
}

How to use the result:

app.post("/login",function(req,res) {
    post.login(req,res,con,mysql,p).then(function(Player) {

    }); 
})
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top