Callback Hell
Приветствую. Нужно чтобы функция, если аккаунт существует, возвращала 1, если нет - 0. При первом вызове выдаёт undefined, дальше как нужно. Видимо что-то с обратными вызовами, помогите исправить:
const mysql = require('mysql')
let r
function isRegistered(id){
var sel_query = con.query('SELECT * FROM `users` WHERE `userid`= ?', id, function GET(error, results, fields) {
if (results.length != 0) {
r = 1
}
else {
r = 0
}
return r
})
return r
}
|
Колбэки работают примерно так:
function isRegistered(id, success, error){
var sel_query = con.query('SELECT * FROM `users` WHERE `userid`= ?', id, function GET(error, results, fields) {
if(error) return error(error, id);
if(!results.length) return error(0, id);
return success(results.length, id);
})
}
function coninueIfRegistered(count, id){
//дальнейший код если зарегестрирован
}
function coninueIfNotRegistered(reason, id){
//дальнейший код если не зарегестрирован
}
isRegistered(id, coninueIfRegistered, coninueIfNotRegistered);
Можно пошаманить с промисами и async await, но пока с этим не разберётесь - лучше не надо. |
isRegistered(bla-bla);
async function isRegistered(id) {
var sel_query = await new Promise( resolve => {
con.query('SELECT * FROM `users` WHERE `userid`= ?', id, function(error, results) {
if(err) console.error(err);
resolve(results);
});
}).then( result => {
return result;
};
if(sel_query.length != 0) {
console.log(1, sel_query);
} else {
console.log(0);
}
}
|
Audaxviator, тогда уж так:
const mysql = require('mysql')
async function isRegistered(id){
var r = await new Promise(resolve => con.query('SELECT * FROM `users` WHERE `userid`= ?', id, function(err, results) {
if(err || !results.length) return resolve(false);
return resolve(true);
}));
return r
}
(async function(){
//основной код тут
let r = await isRegistered(id);
//...
}());
Только человеку не понимающему стути коллбэков это только вред принесёт.) |
@Aetae, @Audaxviator, сердечно благодарю за помощь, пойду учить матчасть :)
|
Aetae, скажите, а разве из js можно работать с БД? Через аякс + PHP понятно, можно.
А выше какие-то query запросы прямо в js идут)) Это как так? Разве так можно? Для подключения к БД ведь логин и пароль нужен будет и его ведь не спрячешь в js. Это не безопасно. |
А, всё я поняла. Это NodeJS там наверное всё иначе работает.
Извините. |
Тэкс. Объясняем "на пальцах" суть колбеков в асинхронных методах.
Вот обычная советская функция, которая присваивает объявленной перед её вызовом переменной значение - так, "как все привыкли":
function foo() {
a = 'aaa';
}
var a;
foo();
console.log(a); // 'aaa'
Полный успех. А давайте сделаем присвоение значения переменной а - асинхронным, вот так:
function foo() {
process.nextTick( () => {
a = 'aaa';
});
}
var a;
foo();
console.log(a); // undefined
Ошибки не случилось - то есть функция переменную видела, к ней благополучно обращалась, - но в текущем "тике" переменной значение, естественно, не присвоено. Причём, оно было ваабщета присвоено - но нам оказалось уже недоступно. А давайте посмотрим, есть ли оно в следующем тике?
function foo() {
process.nextTick( () => {
a = 'aaa';
});
}
var a;
foo();
console.log(a); // undefined
process.nextTick ( () => {
console.log(a); // 'aaa'
});
Таки есть! И чтобы нам её (переменную с присвоенным значением) всё таки добыть и употребить, как раз и потребуется колбек-функция. Тырц:
function foo(cb) {
setImmediate( () => { // setImmediate - это правильная директива для асинхронного исполнения
a = 'aaa';
cb(a);
});
}
var a;
foo( data => {
console.log(data); // 'aaa'
});
console.log(a); // а тут, понятно, как и прошлый раз - undefined
Причём, сначала-то будет выведено undefined из последней строчки, а потом - 'aaa' из колбека. Вот и вся несложная мудрость. Из которой, надеюсь, должно быть понятно, что любой асинхронный метод любую переменную "снаружи" взять-то может - а вот воспользоваться тем, что он с ней сделает, можно только "внутри": либо внутри собственно колбека этого метода, либо внутри промиса (в который обернут, опять же, вызов этого метода с вызовом его колбека) - но "внутри", и не иначе. В "борьбе с асинхронностью" приходится всё время придумывать конструкции для добывания нужных значений в нужном месте. И это хорошо. Извените за внимание. |
Audaxviator,
не совсем понял суть замены process.nextTick на setImmediate (и комментария к последней) |
process.nextTick было типа в демонстрационных целях - буквально "в следующем тике". Нопремер, setTimeout - это тот же nextTick, но с минимальной задержкой 4 миллисекунды (если написать 0 - всё равно будет 4). Но во-первых, задержка при асинхронном исполнении не нужна, а во-вторых, nextTick даёт приоритет первому некст-тику в коде. А если несколько асинхронных операций?
Короче, это не замена, а использование правильной для асинхронного исполнения функции во втором случае. Ну, или чтобы всех запутать или заинтриговать. (Словом, в этом "примитивном" примере будет одинаково работать и то, и то. А "в реальной жизни" используется setImmediate. Оно когда-то было предложено, вроде бы, Микрософтом, и в ихнем Эксплорере, в интерпретаторе JavaScript, присутствует (в других браузерах - не знаю, не проверял). И в Node - конечно, было сразу нативно вписано.) |
| Часовой пояс GMT +3, время: 10:58. |