Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I Broke My Promise

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
like image 590
Sterling Archer Avatar asked Mar 25 '14 18:03

Sterling Archer


People also ask

What should I do if I broke my promise?

Apologize for breaking the promise. Being overly defensive or distancing yourself from the situation makes it sound like this type of promise-breaking could happen at any time because you are not in control. Instead, be accountable and reveal what you plan to do differently in the future.

Is it okay to broke a promise?

IS IT EVER OKAY to break a promise? Generally speaking, no. A promise changes reality by introducing an ingredient that wouldn't exist except for the promise.

What happens if you break a promise to yourself?

As you make those promises, you build momentum. As you break those promises, you lead yourself to the path of inertia, one of the main negative consequences of continued broken promises. Let's take a look at how people end up at the point of inertia, totally stuck.

When you break a promise to a friend?

Give your friend the benefit of the doubt, suggests the Southam Consulting team in “The Ten Secrets to Managing Broken Promises, Violated Expectations, and Bad Behavior.” State the facts as you see them, such as “The paper you promised to help me with is still unfinished," or "You promised you'd come to my dance ...


1 Answers

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) {

    }); 
})
like image 149
Esailija Avatar answered Sep 26 '22 12:09

Esailija