Наруших обещанието си

Така че.. Най-трудно ми е да се науча как да обещавам.

Използвам bluebird (https://github.com/petkaantonov/bluebird), както ми беше предложено - - за да укротя ада си за обратно обаждане, който получавам. Пример:

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;
}

Гадно е, пълно е с обратни извиквания и функцията връща ref преди обратното извикване на заявката да приключи изпълнението.

Решение: обещания!

Опитах се да конвертирам функцията си с помощта на бързия старт.. така че promisefyAll направих своя mysql модул, преди да създам връзката:

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

И написах функцията си, както следва:

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;
    });
}

Но продължавам да получавам TypeError: Cannot call method 'then' of undefined at Object.login (/var/www/post/posts.js:36:22)

И

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

Грешки. Може ли някой да ми помогне да разбера как да прилагам обещания за запитване към моята база данни (правилно)?

Редактиране (приемане на отговор след:): ето как извиквам функцията за влизане:

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

person Sterling Archer    schedule 25.03.2014    source източник
comment
Опитайте да завържете връв около пръста си. Намирам, че помага като ви напомня да спазвате обещанията.   -  person rlemon    schedule 25.03.2014
comment
опитайте да прочетете това: howtonode.org/promises (редактирано ... съжалявам грешно поставяне)   -  person rafaelcastrocouto    schedule 25.03.2014
comment
@rafaelcastrocouto Свързах се с това във въпроса си.   -  person Sterling Archer    schedule 25.03.2014
comment
@rafaelcastrocouto Прочетох и това -- концептуално има смисъл, но използването на различна библиотека с обещания в различен сценарий е различно.   -  person Sterling Archer    schedule 25.03.2014
comment
Гласуващ против - причина? Бих искал да подобря този въпрос.   -  person Sterling Archer    schedule 25.03.2014
comment
@RUJordan Какво връща con.getConnection()? Можете ли да опитате console.loggin it?   -  person thefourtheye    schedule 25.03.2014
comment
Първата грешка е, защото con.getConnection() не връща обещание.   -  person Jebin    schedule 25.03.2014
comment
@thefourtheye, което дава undefined. Но работи перфектно (без връщането на обект) в претрупаната, гадна функция, която се опитвам да преработя.   -  person Sterling Archer    schedule 25.03.2014
comment
+1 само за заглавието   -  person Adam    schedule 25.03.2014
comment
Не забравяйте, че изтичате връзката, ако заявката ви е неуспешна :p   -  person Esailija    schedule 25.03.2014
comment
-1 за напълно безполезно заглавие (и не чета въпроса, за да измисля по-добро)   -  person Dexygen    schedule 03.06.2014
comment
@GeorgeJempty зависи от вас какво ще правите, но отрицателните гласове се основават на качеството на съдържанието, а не на заглавието. ;)   -  person Sterling Archer    schedule 03.06.2014
comment
@RUJordan кажи това на Адам и 7-те, които гласуваха за неговия коментар   -  person Dexygen    schedule 03.06.2014
comment
Коментарът с одобрение не означава, че всички са гласували само заради заглавието. Това може да означава, че са намерили заглавието за умно и въпросът за достоен. Наистина ли е толкова важно за вас?   -  person Sterling Archer    schedule 03.06.2014


Отговори (1)


Когато обещаете прототип, методите за връщане на обещание ще имат суфикс *Async

Идеята на обещанието е да се преструвате, сякаш библиотеката е проектирана да връща обещания като начало. Не трябва да извиквате promisify в кода на приложението по време на изпълнение, а в кода за стартиране на вашето приложение или подобен.

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();
        });
    });
}

Бъдеща версия ще има много по-добро управление на ресурсите и ще можете да правите:

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"
            });
        }
    });
}

Как да използвате резултата:

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

    }); 
})
person Esailija    schedule 25.03.2014
comment
Но ако той използва само два или три метода, защо трябва да прави promisifyAll? promisify трябваше да е достатъчно, нали? - person thefourtheye; 25.03.2014
comment
@thefourtheye Винаги трябва да правите promisifyAll, защото тогава няма нужда да се тревожите за това навсякъде. Също така е по-бързо да се извикват методи, които са обещани с promisifyAll - person Esailija; 25.03.2014
comment
@Esailija благодаря ти много. Това беше буквално копиране и поставяне. Бихте ли могли, ако не е много трудно, да ме свържете с ресурси, които обясняват това, за да мога да науча какво прави разпространението и т.н.? - person Sterling Archer; 25.03.2014
comment
@RUJordan прочете ли readme и Документация за API? - person Esailija; 25.03.2014
comment
@Esailija Ще опитам още веднъж. Този път метод по метод. Благодаря отново. :) - person Sterling Archer; 25.03.2014
comment
@Esailija, когато извикам тази функция за влизане, връщам обекта към променлива в моя сървърен файл -- но продължавам да получавам връщан празен обект. Но когато регистрирам ref преди да бъде върнат, той се регистрира добре. Знаете ли защо се случва това? - person Sterling Archer; 26.03.2014
comment
Разбира се, редактирах въпроса си. Благодаря ви, че отидете над и отвъд, за да разгледате това. - person Sterling Archer; 26.03.2014
comment
@RUJordan функцията login връща обещание, така че трябва да регистрира [object Promise] - person Esailija; 26.03.2014
comment
@Esailija Ммм, пише [object Object] не обещавам. =x - person Sterling Archer; 26.03.2014
comment
@RUJordan странно, може би регистрационните файлове на възлите също обещават по този начин. Във всеки случай функцията не връща стойност, а обещание. Редактирах как да извикам функцията за влизане - person Esailija; 26.03.2014
comment
@Esailija брилянтен. Не мога да ви благодаря достатъчно за това! - person Sterling Archer; 26.03.2014