Dart非async函数如何等待for循环执行完毕后再返回结果
问题根因
你当前代码返回空列表的本质是stacks[i].get()属于异步操作,.then()注册的回调不会同步执行。你在for循环末尾直接return时,所有异步请求还没触发回调,newStacks还没被写入任何值,自然返回空。
注意:Dart是单线程事件循环模型,不存在真正同步阻塞等待异步结果的实现——只要逻辑里有异步请求,就不可能靠同步return直接拿到结果,所有声称能做到同步等待的死循环方案都会直接卡死线程,导致异步回调永远没有执行机会,触发死锁。
你提到平台不支持async/await、不允许返回Future类型,可行的方案是用计数器+结果回调的方式实现,不需要修改异步逻辑,也不需要依赖async语法。
实现步骤
- 给原函数新增一个结果回调参数,用来在所有异步逻辑执行完成后,向外传递最终计算好的列表
- 初始化一个待完成计数器,初始值等于
stacks的总长度 - 每处理完一个
get()请求的回调,就把计数器减1 - 当计数器归0时,说明所有异步请求、内层匹配逻辑都执行完毕,此时调用结果回调传出最终列表即可
- 内层的玩家匹配逻辑可以直接用
List.contains()简化,不需要手写for循环遍历
改造后代码
void getStacks( List<DocumentReference> favoritePlayers, List<DocumentReference> stacks, void Function(List<DocumentReference> finalStacks) onResult, ) { final List<DocumentReference> newStacks = []; int pendingTaskCount = stacks.length; // 边界处理:传入的stacks为空时直接返回空列表 if (pendingTaskCount == 0) { onResult(newStacks); return; } for (var i = 0; i < stacks.length; i++) { stacks[i].get().then((DocumentSnapshot stackSnapshot) { if (stackSnapshot.exists) { final DocumentReference stackPlayer = stackSnapshot['player']; if (favoritePlayers.contains(stackPlayer)) { newStacks.add(stacks[i]); } } // 当前异步任务完成,计数减1 pendingTaskCount--; // 所有任务完成时,通过回调传出结果 if (pendingTaskCount == 0) { onResult(newStacks); } }); } }
调用方式
不要尝试接收函数的return值,所有依赖最终stacks列表的逻辑,全部写到回调函数里:
getStacks(yourFavoritePlayers, yourSourceStacks, (matchedStacks) { // 在这里写后续业务逻辑,matchedStacks就是你要的最终结果 });
无效方案说明
你之前尝试的while/do-while空转等待的方案不可行:单线程下空循环会占满执行资源,事件队列里的.then()回调永远得不到调度执行,计数器永远不会减少,程序会直接卡死无响应。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

