使用 async/await 时,Firebase Cloud Firestore 查询返回 Promise <pending> 而不是已完成
Posted
技术标签:
【中文标题】使用 async/await 时,Firebase Cloud Firestore 查询返回 Promise <pending> 而不是已完成【英文标题】:Firebase Cloud Firestore query returning Promise <pending> instead of fulfilled when using async/await使用 async/await 时,Firebase Cloud Firestore 查询返回 Promise <pending> 而不是已完成 【发布时间】:2020-11-29 01:16:51 【问题描述】:This question 类似,但没有帮助。
目标是将 async/await 与 Firebase Cloud Firestore 查询一起使用,而不是 the Firebase documentation 中的 then/catch Promise 代码。
但是,下面的函数在否定情况下成功拒绝,但返回 Promise <pending>
而不是 Cloud Firestore 文档。
async getUser(emailAddress)
// Return null if @emailAddress blank.
if (!emailAddress)
return null;
// Assume @db points to a Cloud Firestore database. Query only returns one doc.
let query = db.collection('users').where('emailAddress', '==', emailAddress);
try
let querySnapshot = await query.get();
querySnapshot.forEach(function(doc)
return doc.data();
);
catch(e)
console.log('Error getting user: ', e);
【问题讨论】:
【参考方案1】:如果 emailAddress
不为 null 或未定义,则您的函数不返回任何内容,因为forEach()
返回 void。
由于querySnapshot
中只有一个文档,您可以执行以下操作:
async getUser(emailAddress)
// Return null if @emailAddress blank.
if (!emailAddress)
return null;
// Assume @db points to a Cloud Firestore database. Query only returns one doc.
const query = db.collection('users').where('emailAddress', '==', emailAddress);
try
const querySnapshot = await query.get();
return querySnapshot.docs[0].data();
catch(e)
console.log('Error getting user: ', e);
请注意,您的 getUser()
函数本身是异步的,因此您需要在它返回的 Promise 实现时使用 then()
(或 async/await)来获取 doc 值。
const emailAddress = "john@gmail.com";
getUser(emailAddress).
then(userData => ... )
【讨论】:
【参考方案2】:您正试图从forEach
返回,但forEach
不返回任何内容,而是循环遍历元素并允许您修改它们。
您可以像这样修改您的代码,例如:
async getUser(emailAddress)
// Return null if @emailAddress blank.
if (!emailAddress)
return null;
// Assume @db points to a Cloud Firestore database. Query only returns one doc.
let query = db.collection('users').where('emailAddress', '==', emailAddress);
try
const results = [];
let querySnapshot = await query.get();
querySnapshot.forEach(function(doc)
results.push(doc.data());
);
return results;
catch(e)
console.log('Error getting user: ', e);
更多关于forEach的信息:
forEach() 对每个数组元素执行一次回调函数; 不像 map() 或 reduce() 它总是返回值 undefined 并且是 不可链接。典型的用例是在 链的末端。
【讨论】:
【参考方案3】:async
函数,例如你的函数,总是返回一个承诺。这是无法避免的。所有的异步行为仍然存在于函数中,调用者仍然需要await
或then
来获取promise 中的值。你不能使用 async/await 来移除一个 Promise 并立即返回。
最重要的是,您的函数实际上并不返回任何文档。 forEach
中的返回实际上只是从您传递给 forEach
的内联 lambda 函数返回。该返回不会扩展到封闭的 getUser
函数。
如果您想有效地使用 async/await,该函数仍然必须从其顶层返回一个值。调用者仍然需要使用 await 或 then 来从返回的 promise 中获取值。
【讨论】:
以上是关于使用 async/await 时,Firebase Cloud Firestore 查询返回 Promise <pending> 而不是已完成的主要内容,如果未能解决你的问题,请参考以下文章
使用 async / await 在 firebase 中运行查询
将 async/await (Swift 5.5) 与 firebase 实时数据库一起使用
处理 Async Await 以使用 Firebase 和 react native
使用 useEffect() Hook 和 Async/Await 从 Firebase/Firestore 获取数据
async/await 与 firebase .on() 数据库监听器
Firebase:Flutter:避免事务崩溃 CloudFirestorePlugin.java:613 : .then() vs async/await