我在理解为什么我的代码无法正常工作时遇到了一些麻烦。我正在尝试从react-native项目中的firebase读取数据。我可以很好地读取它,但不能将数据设置为任何变量。
这是我的代码。
let tmp;
let userRef = firebase.firestore().collection("Users");
userRef.doc(this.state.FirstName).get().then((document) => {
tmp = document.data().FirstName;
alert(tmp);
})
.catch((errorMsg) => {
alert(errorMsg);
})
alert("tmp Data: " + tmp);
};
问题是,如果我在函数内部向tmp
发出警报,则会按预期显示FirstName变量。但是,当我在函数外部向tmp
发出警报时,它显示为未定义。我只是似乎无法绕开为什么这行不通的想法,如果有人可以告诉我我在这里做错了什么,我将不胜感激。
答案 0 :(得分:3)
这是完全正常的。发生这种情况的原因是,如果将alert
放在该块之外,那么它将在该块之前执行,而tmp
尚未初始化。从数据库获取FirstName
的代码(get()
函数)在另一个线程中执行一些代码,并且您的原始线程继续运行而无需等待其完成。当另一个线程完成执行时,将执行该块中的代码。您可以通过在块的之前,内部和之后添加alert
来验证此行为,以查看执行顺序。要了解更多信息,请阅读有关asynchronous operations和promises的信息。
为什么所有这些?为什么get()
在另一个线程中执行某些代码?简而言之,因为它使用网络访问Firebase数据库,并且可能需要一些时间才能返回响应。如果get()
在同一调用线程中执行“网络代码”,则从主线程(UI线程)进行调用将使您的UI无响应,直到响应返回。因此,相反,get()
将“网络代码”调度到另一个线程,并甚至在“网络代码”完成执行之前立即返回promise
对象。您可以使用该promise
对象指定结果到达时要执行的操作。这样,调用线程将继续执行,而无需等待,并且在调用线程是UI线程的情况下(通常是这种情况),这意味着您的UI始终是响应式的。