Flutter中async/await执行不符合预期的问题排查与解决
问题描述
标记为async的getData函数通过await获取notes时执行顺序滞后,控制台先输出null和NO NOTES,之后才输出Firestore返回的正确数据。该代码此前可正常运行,仅修改Flutter版本后出现问题,升级版本仍未解决。
已实现FirestoreHelper类,其静态方法getUserDataFromDataField用于根据指定字段获取用户数据:
class FirestoreHelper{ static Future<dynamic> getUserDataFromDataField(String documentFieldName, String userEmail) async{ final db = FirebaseFirestore.instance; final docRef = db.collection("users_data").doc(userEmail); docRef.get().then( (DocumentSnapshot doc) { final data = doc.data() as Map<String, dynamic>; print('FIRESTORE HELPER'); print(data[documentFieldName]); return data[documentFieldName]; }, onError: (e) => print("Error getting document: $e"), ); } }
调用代码:
void getData() async{ List<dynamic>? notes = await FirestoreHelper.getUserDataFromDataField('notes', user.email!); print(notes); if(notes == null){ print('NO NOTES'); } else { print('NOTES FOUND'); } }
控制台输出顺序:
null NO NOTES FIRESTORE HELPER [{29, 4, 2023: ['NoteTitle', 'noteDescription']}] (正确数据)
问题原因
核心问题是getUserDataFromDataField方法存在逻辑错误:
- 方法标记为
async,但没有返回异步操作的Future。内部使用docRef.get().then(...)处理异步结果,但未将这个then返回的Future作为方法的返回值。 - 由于方法没有返回有效Future,
async修饰的方法会默认返回一个已完成的空Future,导致调用await时直接拿到null,后续then里的Firestore数据读取操作才在后台执行,从而出现输出顺序颠倒的情况。
解决方法
推荐改用await替代then回调(更符合async/await规范,避免回调嵌套),同时正确返回数据并处理错误:
修改后的FirestoreHelper代码:
class FirestoreHelper{ static Future<dynamic>? getUserDataFromDataField(String documentFieldName, String userEmail) async{ final db = FirebaseFirestore.instance; final docRef = db.collection("users_data").doc(userEmail); try { final DocumentSnapshot doc = await docRef.get(); final data = doc.data() as Map<String, dynamic>; print('FIRESTORE HELPER'); print(data[documentFieldName]); return data[documentFieldName]; } catch(e) { print("Error getting document: $e"); return null; // 错误时返回null,也可根据需求抛出异常 } } }
如果坚持使用then,需确保方法返回then的Future:
class FirestoreHelper{ static Future<dynamic> getUserDataFromDataField(String documentFieldName, String userEmail) { final db = FirebaseFirestore.instance; final docRef = db.collection("users_data").doc(userEmail); return docRef.get().then( (DocumentSnapshot doc) { final data = doc.data() as Map<String, dynamic>; print('FIRESTORE HELPER'); print(data[documentFieldName]); return data[documentFieldName]; }, onError: (e) { print("Error getting document: $e"); return null; }, ); } }
修改后,await会等待Firestore异步操作完成后再继续执行,控制台输出顺序会变为:
FIRESTORE HELPER [{29, 4, 2023: ['NoteTitle', 'noteDescription']}] (正确数据) [{29, 4, 2023: ['NoteTitle', 'noteDescription']}] NOTES FOUND
内容的提问来源于stack exchange,提问作者Sohatzky
相关产品推荐
相关产品推荐

