Проблема в том, что запрос Firestore является асинхронным, но вы не ждете ответа, прежде чем продолжить. По сути, у вас есть следующее:
getDefaultAnswer () {
var data
// This next bit is asynchronous
db.doLotsOfStuff().then(querySnapshot => {
// This callback won't have been called by the time the outer function returns
querySnapshot.forEach(doc => {
data = doc.data()
})
})
return data
},
Асинхронный вызов Firestore будет выполняться в фоновом режиме. Между тем остальная часть кода в getDefaultAnswer
будет продолжать работать синхронно.
Таким образом, в тот момент, когда код достигает return data
, ни один из кодов внутри обратного вызова then
не будет запущен. Вы можете подтвердить это, введя некоторые записи в консоли, чтобы увидеть, в каком порядке выполняется код.
Использование then
для работы с асинхронным кодом является функцией Promises. Если вы еще не знакомы с Обещаниями, вам следует изучить их подробно, прежде чем идти дальше. Вот одно из многих доступных руководств:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
Суть в том, что вы не можете заставить метод getDefaultAnswer
ждать асинхронного действия для полный. Вместо этого вы можете вернуть подходящее обещание, а затем дождаться разрешения этого обещания, прежде чем позвонить onNotSelectedAnswer
. Это может выглядеть примерно так:
getDefaultAnswer () {
// We return the Promise chain from getDefaultAnswer
return db.doLotsOfStuff().then(querySnapshot => {
var data = null
// I have assumed that forEach is synchronous
querySnapshot.forEach(doc => {
data = doc.data()
})
// This resolves the Promise to the value of data
return data
})
},
Важно понимать, что метод getDefaultAnswer
не пытается вернуть значение данных. Вместо этого он возвращает Обещание, которое будет resolve
равным значению данных.
В пределах CountTerminated
вы затем будете использовать его следующим образом:
this.getDefaultAnswer().then(defaultAnswer => {
this.onNotSelectedAnswer(defaultAnswer)
})
или, если вы предпочитаете:
this.getDefaultAnswer().then(this.onNotSelectedAnswer)
Последнее является более кратким, но не обязательно более ясным.
Вы также можете написать его, используя async
/ await
, но я бы не советовал пытаться использовать async
/ await
пока у вас не будет solid гр asp того, как работают Обещания. Хотя async
/ await
может быть очень полезным для исправления кода, это всего лишь небольшая оболочка для Обещаний, и вам нужно понимать Обещания для устранения любых проблем.
Код, который я предложил выше, должен работать, но есть задержка, пока он ожидает завершения асинхронного запроса. В этой задержке могут произойти вещи, например, пользователь может нажать на кнопку. Это может привести к дальнейшим проблемам.
Альтернативой может быть загрузка ответа по умолчанию намного раньше. Не ждите, пока он вам действительно не понадобится. Возможно, загрузите его, как только появится вопрос. Сохраните результат где-нибудь доступным, возможно, в подходящем data
свойстве, чтобы оно было доступно, как только оно вам понадобится.