Невозможно изменить значение глобального var

# #javascript #firebase #firebase-realtime-database

Вопрос:

Редактировать: Пришлось опубликовать это, потому что кто-то пометил его как дубликат и связал с неуместным вопросом о возврате значения асинхронных функций, что не помогло.

Я застрял на этом большую часть дня. У меня есть глобальный параметр var user_dict, который я инициирую значением, а затем пытаюсь изменить в функции. Значение просто не изменится.

Используя список просмотра во время отладки, я создал видео, показывающее, что я имею в виду. Кто-нибудь может помочь мне понять, что здесь происходит?

https://streamable.com/o498yu

Я знаю, что мне нужно включить код с внешними ссылками, но проблема не воспроизводима без предоставления доступа к моей базе данных 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 другой переменной и не использовал ваш точный синтаксис, теперь он работает.