Dart对象创建中的嵌套await问题:含sections的分类异步处理
当你在map回调里使用async =>时,会遇到一个关键问题:你得到的不再是包含解析后Map的列表,而是一堆未完成的Future对象,这和你预期的嵌套数据结构完全不符。
为什么会这样?
原来的getCategories()返回的是Stream<Category>,当你调用.map((category) async => {...})时,async关键字会让这个回调函数返回一个Future<Map<String, dynamic>>。这就导致整个map操作后的Stream变成了Stream<Future<Map<String, dynamic>>>,而不是你想要的Stream<Map<String, dynamic>>。
当你后续调用.toList()并await它时,你得到的是List<Future<Map<String, dynamic>>>——也就是一堆还没执行完的异步任务,而不是已经解析好的Map数据。打印出来的结果会类似:
{categories: [Instance of 'Future<Map<String, dynamic>>', Instance of 'Future<Map<String, dynamic>>']}
两种解决办法
1. 使用asyncMap替代map
Dart的Stream提供了asyncMap方法,它专门用来处理返回Future的回调。asyncMap会自动等待每个Future完成,然后把结果发射出去,最终得到的是Stream<Map<String, dynamic>>,这样后续的toList()就能直接得到你想要的列表:
final data = { 'categories': await getCategories() .asyncMap((category) async => { 'id': category.id, // 假设category.sections是Stream<Section>;如果是Future<List<Section>>,直接await即可 'sections': await category.sections .map((section) => {'id': section.id}) .toList() }) .toList() }; // 输出预期的嵌套结构:{categories: [{id: 0, sections: [{id: 0}]}, ...]} print(data);
2. 用Future.wait()等待所有Future完成
如果你坚持要用map,可以先把Stream转换成List<Future<Map>>,然后用Future.wait()来等待所有异步任务执行完成,得到最终的解析后列表:
// 先获取所有未完成的Future列表 final categoryFutures = await getCategories() .map((category) async => { 'id': category.id, 'sections': await category.sections .map((s) => {'id': s.id}) .toList() }) .toList(); // 等待所有Future完成,得到解析后的Map列表 final data = { 'categories': await Future.wait(categoryFutures) }; print(data);
额外注意
如果category.sections不是Stream,而是Future<List<Section>>类型,那么你只需要直接await category.sections,不需要再调用.toList(),比如:
'sections': (await category.sections).map((s) => {'id': s.id}).toList()
内容的提问来源于stack exchange,提问作者Cequiel

