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, время: 01:31. |