Firestore查询函数提前返回致数组未填充问题排查与解决
Firestore查询返回空数组问题:原因与修复
问题场景
我尝试从Firestore数据库的集合中展示所有文档,编写了如下查询代码,但函数总是在recipes数组填充完成前就返回,导致print(recipes)输出空数组[]:
class DatabaseService { static List<Recipe> getSavedRecipes(String uid) { List<Recipe> recipes = []; FirebaseFirestore.instance .collection("users") .doc(uid) .collection('saved recipes') .get() .then( (querySnapshot) { print("Successfully completed"); for (var docSnapshot in querySnapshot.docs) { recipes.add(Recipe.fromFirestore(docSnapshot)); } }, onError: (e) => print("Error completing: $e"), ); print(recipes); return recipes; // 竞态条件:数组还没填充就返回了 } }
问题原因
Firestore的get()方法是异步操作,它会立即返回一个Future对象,不会阻塞后续代码执行。原函数是同步函数,then()中的回调逻辑要等Firestore返回数据后才会执行,但此时print(recipes)和return recipes已经执行完毕,所以返回的是空数组,这是典型的异步操作竞态问题。
解决办法
- 将函数声明为异步函数,添加
async关键字 - 把函数返回类型从
List<Recipe>改为Future<List<Recipe>>,因为异步操作的结果是一个Future对象 - 使用
await关键字等待Firestore的get()操作完成,确保数据填充完毕后再返回数组
修复后的代码
class DatabaseService { static Future<List<Recipe>> getSavedRecipes(String uid) async { late List<Recipe> recipes = []; final docs = FirebaseFirestore.instance .collection("users") .doc(uid) .collection('saved recipes') .get(); await docs.then( (querySnapshot) { print("Successfully completed"); for (var docSnapshot in querySnapshot.docs) { recipes.add(Recipe.fromFirestore(docSnapshot)); } }, onError: (e) => print("Error completing: $e"), ); return recipes; } }
可选优化(更简洁的写法)
可以去掉then(),直接用await获取查询结果,代码可读性更高:
class DatabaseService { static Future<List<Recipe>> getSavedRecipes(String uid) async { try { final querySnapshot = await FirebaseFirestore.instance .collection("users") .doc(uid) .collection('saved recipes') .get(); print("Successfully completed"); return querySnapshot.docs .map((doc) => Recipe.fromFirestore(doc)) .toList(); } catch (e) { print("Error completing: $e"); return []; } } }
内容的提问来源于stack exchange,提问作者Hugh Mungus
相关产品推荐
相关产品推荐

