Dart中forEach与for循环使用async/await的执行顺序差异问题
Dart 异步循环执行顺序问题解析
执行顺序差异的原因
- Dart 内置的
Iterable.forEach方法设计为同步执行,不会等待传入的异步回调执行完成:你给forEach传入的async函数虽然内部有await,但forEach只会遍历调用所有回调,不会收集回调返回的Future也不会等待这些Futureresolve,因此forEach遍历完成后就会立刻执行后续的segregate()方法,此时回调内的异步操作还没完成。 - 普通for循环的
await是写在当前getData这个异步函数的上下文中,每次循环的await都会暂停当前函数执行,等待本次异步操作完成后再进入下一次循环,所有循环逻辑执行完成后才会走到后续的segregate(),因此顺序符合预期。 - 观察到的forEach速度更快,本质是异步并发带来的效率差异:forEach遍历的时候会一次性发出所有的
fetchOrderedProducts请求,不需要等待前一个请求返回就发下一个;而普通for循环是串行发请求,前一个请求返回后才会发下一个,因此前者总耗时更短,不是forEach本身的执行效率高于普通for循环。
forEach场景下的异步逻辑正确实现
如果需要保留并发请求的高效率,同时保证所有异步操作完成后再执行后续逻辑,可以使用Future.wait搭配map实现,代码示例如下:
Future getData() async { var results = await DatabaseHandler().fetchOrders("merchantId"); // 等待所有异步请求执行完成 await Future.wait(results.docs.map((f) async { var products = await DatabaseHandler().fetchOrderedProducts(f.id); var productData = products.data(); // 往mainOrdersList添加数据的逻辑写在这里 print("mainOrderList Length - ${mainOrdersList.length}"); })); // 所有异步操作完成后再执行分类和刷新 segregate(); setState(() {}); }
注意:如果业务逻辑要求必须按
docs的顺序依次执行请求,不能并发,那还是用普通for循环的写法更合适。
内容的提问来源于stack exchange,提问作者Mayur Agarwal
相关产品推荐
相关产品推荐

