Я нарушил свое обещание

Итак.. Мне очень трудно научиться обещать.

Я использую 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
Downvoter - причина? Я хотел бы улучшить этот вопрос.   -  person Sterling Archer    schedule 25.03.2014
comment
@RUJordan Что возвращает con.getConnection()? Можете ли вы попробовать console.loggin это?   -  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.

Идея промисификации состоит в том, чтобы притвориться, что библиотека с самого начала предназначена для возврата промисов. Вы не должны вызывать обещание в коде приложения во время выполнения, но в коде начальной загрузки вашего приложения или аналогичном.

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] не обещаю. =х - person Sterling Archer; 26.03.2014
comment
@RUJordan странно, может быть, журналы узлов тоже обещают это. В любом случае функция возвращает не значение, а обещание. Я отредактировал способ вызова функции входа в систему - person Esailija; 26.03.2014
comment
@Esailija молодец. Я не могу отблагодарить вас за это! - person Sterling Archer; 26.03.2014