# #javascript #firebase #firebase-realtime-database
Вопрос:
Редактировать: Пришлось опубликовать это, потому что кто-то пометил его как дубликат и связал с неуместным вопросом о возврате значения асинхронных функций, что не помогло.
Я застрял на этом большую часть дня. У меня есть глобальный параметр var user_dict, который я инициирую значением, а затем пытаюсь изменить в функции. Значение просто не изменится.
Используя список просмотра во время отладки, я создал видео, показывающее, что я имею в виду. Кто-нибудь может помочь мне понять, что здесь происходит?
Я знаю, что мне нужно включить код с внешними ссылками, но проблема не воспроизводима без предоставления доступа к моей базе данных Firebase, следовательно, видео. Однако это важная часть моего кода.
При отладке строка за строкой getUserDict() возвращает «none_found», как и должно быть, но значение user_dict никогда не меняется. Мне нужно, чтобы getUserDict() закончил до checkUserDict (), но я не могу заставить обещание работать.
var user_dict
userLogin()
function userLogin() {
console.log('userLogin')
if (checkLogin()) {
console.log('userLogin checkLogin is true')
user_dict = getUserDict().then(checkUserDict())
}
}
function getUserDict() {
let current_user_id = firebase.auth().currentUser.uid
let snapshot = firebase.database().ref().child('profile').child(current_user_id).child('user_dict').once('value')
if (snapshot.exists) {
return snapshot.val()
} else {
return 'none_found'
}
}
function checkUserDict() {
if (user_dict === 'none_found') {
console.log('userLogin unable to find user_dict, preparing needed data')
user_dict = getQuestions().then(createProfile())
} else {
console.log('userLogin user_dict is ', user_dict)
handleWelcome(is_first_time = false)
}
}
Комментарии:
1. Не делай этого, это бесплатный билет в хаос. В настоящее время вы не можете изменить значение, позже вы не узнаете, почему оно изменилось, работа с побочными эффектами-это анти-шаблон
2. Чего мне не следует делать?
Ответ №1:
Ваш код не ждет, пока обещания разрешатся, вот почему он просто проходит, и ничего не меняется. Вы можете использовать async/await
или then/catch
заставить свой код ждать и обновлять в нужном вам порядке.
Вот как это может работать, используя then/catch
, как вы уже пытаетесь реализовать этот шаблон.
var user_dict
userLogin()
function userLogin() {
console.log('userLogin')
if (checkLogin()) {
console.log('userLogin checkLogin is true')
getUserDict().then((value) => {
// See NOTE below for what "value" is here
user_dict = value
checkUserDict()
})
}
}
// NOTE
// This function will now wait for Firebase to return and then this
// function will return the snapshot value or a string of `none_found`
function getUserDict() {
const current_user_id = firebase.auth().currentUser.uid
return firebase.database().ref().child('profile').child(current_user_id).child('user_dict').once('value').then(snapshot => {
if( snapshot.exists ) {
return snapshot.val()
}
return 'none_found'
})
}
function checkUserDict() {
if (user_dict === 'none_found') {
console.log('userLogin unable to find user_dict, preparing needed data')
user_dict = getQuestions().then(createProfile())
} else {
console.log('userLogin user_dict is ', user_dict)
handleWelcome(is_first_time = false)
}
}
Я изменил ваш существующий код, чтобы он работал, но я также хотел бы отметить, что, как правило, плохая практика-использовать глобальные значения, когда область видимости переменной является опцией. Я недостаточно знаю о других ваших функциях, чтобы написать правильный пример, но вы можете заглянуть в область переменных и пообещать, что цепочка поможет.
Комментарии:
1. Вероятно, стоит подчеркнуть, что
checkUserDict()
это также не обрабатывает егоundefined
состояние, если оно вызывается слишком рано.2. Спасибо, думал, что это не сработало, но я понял, что все еще пытаюсь присвоить значение getUserDict другой переменной и не использовал ваш точный синтаксис, теперь он работает.