Flutter异步函数randomChat返回空值问题求助
Flutter异步函数randomChat返回空值问题排查与修复
调用randomChat异步函数时,返回结果为空,不符合预期逻辑。以下是相关代码及问题根源分析:
相关代码
randomChat函数
Future<String> randomChat(String userId) async { String roomId = await connectRoom(userId); return roomId; }
connectRoom函数(问题核心所在)
Future<String> connectRoom(String userId) async { List<String> connectedUsers = await getChattingWith(userId); late String roomId; // 查找所有userId2为空的房间 FirebaseFirestore.instance .collection('rooms') .where('userId2', isEqualTo: "") .where("userId1", isNotEqualTo: userId) .get() .then((snapshot) async { // 如果没找到空房间,创建新房间 if (snapshot.docs.isEmpty) { print("call empty"); String roomId = await createRoom(userId); return roomId; } // 查找未与当前用户连接的空房间并加入 for (int i = 0; i < snapshot.docs.length; i++) { var data = snapshot.docs[i].data(); Room room = Room.fromJson(data); // 检查该空房间是否已与当前用户连接 bool found = connectedUsers.contains(room.userId1); if (!found) { FirebaseFirestore.instance .collection('rooms') .doc(room.id) .update({"userId2": userId}); print("call not found = $roomId"); return roomId = room.id; } else { roomId = await createRoom(userId); print("call found = $roomId"); return roomId; } } }); print("call nothing = $roomId"); return roomId; }
调用代码(打印结果为空)
onPressed: () async { String roomId = await randomChat(uid); print(roomId); },
createRoom函数(可正常返回roomId)
Future<String> createRoom(String userId) async { DocumentReference docRef = await FirebaseFirestore.instance.collection("rooms").add({ "userId1": userId, "userId2": "", "created_at": DateTime.now().toString(), }); await docRef.update({"roomId": docRef.id}); print("create room: ${docRef.id}"); return docRef.id; }
问题根源
connectRoom函数中混用了then回调和async/await,导致异步逻辑出现竞态:
- 外层代码调用Firestore查询后,没有等待
then回调执行完成,就直接执行到最后的print并返回roomId - 此时
roomId虽声明为late,但并未被then回调中的逻辑赋值(then里的return只是回调函数的返回值,不会改变外层函数的返回结果)
修复方案
将then回调替换为await,统一使用async/await写法,确保函数等待Firestore操作完成后再返回结果:
Future<String> connectRoom(String userId) async { List<String> connectedUsers = await getChattingWith(userId); // 用await等待Firestore查询结果 final snapshot = await FirebaseFirestore.instance .collection('rooms') .where('userId2', isEqualTo: "") .where("userId1", isNotEqualTo: userId) .get(); // 无空房间则创建新房间 if (snapshot.docs.isEmpty) { print("call empty"); return await createRoom(userId); } // 遍历空房间,查找可加入的目标 for (int i = 0; i < snapshot.docs.length; i++) { var data = snapshot.docs[i].data(); Room room = Room.fromJson(data); bool found = connectedUsers.contains(room.userId1); if (!found) { // 等待房间更新完成再返回 await FirebaseFirestore.instance .collection('rooms') .doc(room.id) .update({"userId2": userId}); print("call not found = ${room.id}"); return room.id; } else { final newRoomId = await createRoom(userId); print("call found = $newRoomId"); return newRoomId; } } // 兜底逻辑:循环结束仍无结果则创建新房间 final fallbackRoomId = await createRoom(userId); print("call fallback = $fallbackRoomId"); return fallbackRoomId; }
修复说明
- 移除
then回调,用await等待异步操作完成,保证逻辑执行顺序 - 去掉不必要的
late变量声明,直接通过return返回结果,避免未初始化风险 - 给Firestore的
update操作添加await,确保房间状态更新完成后再返回ID - 增加兜底逻辑,增强代码健壮性
内容的提问来源于stack exchange,提问作者cipano
相关产品推荐
相关产品推荐

