为何使用async函数查询Firestore数据库会得到两种不同输出?
这其实是JavaScript中async函数的核心特性导致的,和Firestore API本身没有关系,咱们一步步拆解清楚:
首先记住这条铁律:所有被async关键字修饰的函数,不管内部逻辑如何,它的返回值都会被自动包装成一个Promise对象。哪怕你在函数里return的是一个普通的JSON对象、数字或者字符串,JS都会把它变成一个处于resolved状态的Promise;如果函数里抛出错误,返回的就是rejected状态的Promise。
咱们回头看你的两段代码:
第一段代码的逻辑
你调用了getDocument(aDatabase, aPath),但并没有去接收它的返回值。函数内部的await cityRef.get()已经帮你等待了Firestore异步请求完成,所以内部的console.log能正常拿到doc.data()的结果。整个函数的Promise返回值没有被使用,所以你不会感受到它的存在。
第二段代码的问题
当你把getDocument()的结果赋值给docData时,本质上是把这个async函数返回的Promise对象赋给了变量,而不是直接拿到doc.data()的结果。这时候docData自然是一个pending状态的Promise(因为异步操作可能还没完成),必须通过.then()回调或者await来提取内部的实际数据。
修正的写法
如果想直接拿到doc.data()的结果,有两种常用方式:
- 在async函数内部使用await:
async function main() { const aDatabase = admin.firestore(); const aPath = 'path/to/document'; const docData = await getDocument(aDatabase, aPath); console.log('docData:', docData); } main();
- 用.then()处理Promise:
const aDatabase = admin.firestore(); const aPath = 'path/to/document'; getDocument(aDatabase, aPath).then(docData => { console.log('docData:', docData); });
再补充一句:Firestore的get()方法本身就是异步的,返回Promise,你用await等待它完成后拿到的doc是实际的DocumentSnapshot(这里你提到的DocumentQuerySnapshot可能是笔误),但整个getDocument因为是async函数,所以它的返回必然是Promise,这是JS异步编程的既定规则,和Firestore的API设计无关。
内容的提问来源于stack exchange,提问作者marco

