Flutter Dart中for循环处理Future未等待执行完成如何修复
问题原因
- Dart内置的
Iterable.forEach方法不支持等待异步回调执行完成,你传入的async回调执行到await处就会暂时挂起,但forEach本身不会等待这些回调全部执行结束,而是同步完成遍历后就继续走后续逻辑,最终导致还没等所有NodeCard添加完成,方法就提前返回了还没填充完的nodeCards数组。
修复方案
把forEach遍历替换成支持异步等待的Future.wait配合普通for循环,或者直接用for-in遍历所有键值对,等待每个异步操作完成。这里推荐用Future.wait同时执行所有异步请求,效率比串行等待更高,修改后的代码如下:
class NodeCardBuilder { Future<List<Widget>> getCurrentUserNodes(BuildContext passedContext) async { List<Widget> nodeCards = []; List nodes = await FirebaseHelper().getNodeList(); Size size = MediaQuery.of(passedContext).size; nodeCards.add(SizedBox(height: size.height * 0.2, width: size.width)); // 存储所有异步操作的Future列表 List<Future> asyncTasks = []; for (Map node in nodes) { // 遍历每个node的键值对,把异步任务加到列表里 node.forEach((key, value) { asyncTasks.add(() async { List vpsData = await VpsHelper(value['ip'], 22, 'root', value['pass']) .getVpsData(); nodeCards.add(NodeCard( key, value['ethAdd'], double.parse(vpsData[0]) / 100, double.parse(vpsData[1]) / 100, double.parse(vpsData[2]) / 100, )); }()); }); } // 等待所有异步任务全部执行完成再返回 await Future.wait(asyncTasks); return nodeCards; } }
注意事项
- 如果你需要严格按照遍历的顺序生成
NodeCard,可以把Future.wait换成串行等待的写法,不过接口请求总耗时会变长:
for (Map node in nodes) { for (var entry in node.entries) { final key = entry.key; final value = entry.value; List vpsData = await VpsHelper(value['ip'], 22, 'root', value['pass']) .getVpsData(); nodeCards.add(NodeCard( key, value['ethAdd'], double.parse(vpsData[0]) / 100, double.parse(vpsData[1]) / 100, double.parse(vpsData[2]) / 100, )); } }
内容的提问来源于stack exchange,提问作者Kish Arora
相关产品推荐
相关产品推荐

