Это происходит из-за того, как работают обратные вызовы. В этом коде:
client.query('SELECT id FROM user WHERE username=? AND password=?',[reg.body.user, req.body.pass],
function(err, results,fields) {
if (err || results.length == 0) {
login_error=1;
console.log('a '+login_error); //LINE A
}
});
функция, содержащая строку A, не выполняется немедленно. Вместо этого client.query немедленно возвращается, и выполнение продолжается, по направлению к строке B.
Затем, когда возвращается запрос выбора, выполняется функция обратного вызова. Таким образом, в порядке выполнения, он, вероятно, придет после строки B, даже если он появляется в источнике заранее.
Рассмотрим этот пример
client.query('SELECT 1 AS Res', function(err, results) {
console.log(results.fields.Res);
});
client.query('SELECT 2 AS Res', function(err, results) {
console.log(results.fields.Res);
});
вы вполне можете найти это, производя следующий вывод:
2
1
Поскольку второй запрос может возвращаться быстрее, чем первый.
Это источник силы Node - код не блокируется, он асинхронный, поэтому он быстрый .
Чтобы ваш пример работал так, как задумано, вы должны реорганизовать его для вызова кода, который должен знать о результатах запроса, в отдельной функции. Например, что-то вроде этого:
function processLogin(login_error) {
console.log('b '+login_error); //LINE B
if (login_error !== true) {
req.session.username=req.body.user;
}
res.render('login', {
user: req.session.username,
login_error: login_error
});
}
app.post('/login', function(req, res){
if (!req.session.username) { //if no one is logged in
if (req.body.user != undefined && req.body.pass != undefined) {
client.query('USE data', function(error, results) {}
});
client.query('SELECT id FROM user WHERE username=? AND password=?',[reg.body.user, req.body.pass], function(err, results,fields) {
if (err || results.length == 0) {
process_login(true);
} else {
process_login(false);
}
});
}
client.end();
}
Этот код не будет работать сразу, но обратите внимание, как я переместил вызов res.render в функцию, которую я вызываю из обратного вызова client.query. Теперь вам нужно разрешить этому обратному вызову доступ к переменной res, либо сделав его глобальным (что хорошо, если вы находитесь внутри выделенного модуля 'login', но в противном случае это плохая идея), либо передав его в функция в качестве аргумента, который может быть предпочтительным.
То, что строка кода появляется после другой, не обязательно означает, что она будет выполнена после нее, если задействован обратный вызов. То, что действует аналогично, с которым вы, возможно, знакомы, это тайм-ауты; Учтите это:
setTimeout(function() {
console.log(1);
}, 1000);
console.log(2);
В этом случае должно быть очевидно, что вы увидите следующее:
2
1
Точно так же с обратными вызовами к таким вещам, как запросы MySQL. Вместо всего процесса, ожидающего возврата client.query, выполнение продолжается, и вы помещаете все, что зависит от результатов client.query, в обратный вызов, который вы отправляете в client.query.