动态代码字符串列表异步批量取事件:求类似Promise.all的实现方案
解决Dart中动态列表的并行异步请求(类似JS Promise.all)
我明白你的需求啦——想把当前串行执行的异步请求改成并行模式,就像JavaScript里的Promise.all()那样,用Future.wait()来实现对吧?你的当前代码是逐个await每个请求,效率比较低,还要手动判断是否全部完成,确实可以用Future.wait()来简化并提升性能。
先说说你当前代码的问题
你现在的循环里每次都await serviceDataSource.fetchPackageEvents(packageNumber),这意味着每个请求都要等前一个完全完成才会发起下一个,属于串行执行,总耗时是所有请求时间的总和。而且手动判断packagesData.length == packages.length其实没必要,循环结束后自然就收集完所有数据了,但串行的效率问题还是存在。
用Future.wait()实现并行请求(类似Promise.all)
其实Future.wait()完全支持动态生成的Future列表,不管你的packages是动态还是静态的,只要把所有异步任务先创建出来,再交给Future.wait()等待全部完成即可,代码会简洁很多,而且是并行执行,总耗时等于最长的那个请求的时间。
替换后的代码如下:
// 1. 先为每个package生成对应的异步任务(注意这里不要加await,让任务立即并行启动) final List<Future<BuiltList<Event>>> futures = packages .map((packageNumber) => serviceDataSource.fetchPackageEvents(packageNumber)) .toList(); // 2. 等待所有异步任务完成,得到结果列表(顺序和packages的顺序完全对应) final List<BuiltList<Event>> packagesData = await Future.wait(futures); // 3. 所有任务完成后,调用持久化方法 return persistAllPackagesData(packagesData);
代码解释
packages.map(...)会遍历每个packageNumber,生成对应的fetchPackageEventsFuture对象,因为没有用await,这些Future会立即并行发起请求,而不是等前一个完成才开始。Future.wait(futures)会阻塞直到所有Future都执行完成,然后返回一个结果列表,列表中每个元素的顺序和你传入的Future列表顺序一致,也就是第一个packageNumber的结果对应列表的第一个位置,完全不用担心顺序混乱。- 不需要再手动判断列表长度,因为
Future.wait()完成后,packagesData的长度肯定和packages的长度一致。
可选:处理单个请求的异常
如果担心某个请求失败导致整个Future.wait()抛出异常,可以为每个Future添加异常捕获,保证其他请求能正常执行:
final List<Future<BuiltList<Event>>> futures = packages .map((packageNumber) => serviceDataSource.fetchPackageEvents(packageNumber) .catchError((error) { // 这里可以自定义异常处理逻辑,比如返回空列表或者默认值 print("获取package $packageNumber事件失败: $error"); return BuiltList<Event>(); }) ) .toList();
这样即使某个请求失败,其他请求依然会继续执行,Future.wait()会返回包含默认值的结果列表,不会中断整个流程。
内容的提问来源于stack exchange,提问作者Bernardo Mesquita




