Firestore递归提取数据异常:仅返回非引用字段,求排查方案
问题分析与解决方案
问题出在forEach的异步回调不会被等待。你在data.forEach里使用了async回调函数,但forEach方法本身不会等待这些异步操作完成。当遍历结束后,函数直接返回了result,此时那些处理DocumentReference的异步任务还在后台执行,还没来得及把嵌套数据存入result,所以最终返回的只有非引用字段。
修复方案
使用Future.wait等待所有字段的异步处理任务完成后再返回结果,以下是两种可行的实现方式:
方式一:通过Future.wait等待所有异步赋值完成
Future<Map<String, dynamic>> getDetailsByDocumentReference(DocumentReference ref) async { final document = await ref.get(); final data = document.data() as Map<String, dynamic>; final Map<String, dynamic> result = {}; // 收集所有字段处理的Future final fieldFutures = data.entries.map((entry) async { final field = entry.key; final value = entry.value; if (value is DocumentReference) { result[field] = await getDetailsByDocumentReference(value); } else { result[field] = value; } }); // 等待所有异步任务执行完毕 await Future.wait(fieldFutures); return result; }
方式二:生成键值对Future列表,再组装成Map
Future<Map<String, dynamic>> getDetailsByDocumentReference(DocumentReference ref) async { final document = await ref.get(); final data = document.data() as Map<String, dynamic>; // 遍历每个字段,生成包含键值对的Future final entryFutures = data.entries.map((entry) async { final value = entry.value; if (value is DocumentReference) { return MapEntry(entry.key, await getDetailsByDocumentReference(value)); } else { return MapEntry(entry.key, value); } }); // 等待所有Future完成,再将键值对转为Map final entries = await Future.wait(entryFutures); return Map.fromEntries(entries); }
原理说明
Future.wait会接收一个Future列表,等待所有Future执行完成后才继续往下执行,确保所有嵌套的DocumentReference都被异步获取并解析完成。- 原来的forEach遍历中,异步回调是"fire and forget"的模式,函数不会等待这些回调完成就返回结果,导致嵌套数据缺失。
内容的提问来源于stack exchange,提问作者user3013860
相关产品推荐
相关产品推荐

