dart以同步方式调用异步函数引发的时序bug

在写代码的时候,碰到了一个时序问题,记录下来。

背景

问题是这样的,一开始是需要读取数据库里面的数据,读到数据之后把数据赋值给状态管理器riverpod,然后列表自动刷新,因为列表watch了状态管理器的数据,于是有了这一段代码

dart 复制代码
void refreshData() async{
  //从读取数据
  final data = await readDataBase();
  //给状态管理器赋值
  state = data;
}

Future<String> readDataBase() async {
  return "假数据";
}
void main(){
  print("初始化");
  refreshData();
## }

逻辑很简单,因为是响应式的,所以数据更新了会去自动更新列表,到这里是正常的;然后又来了个需求,需要刷新完数据之后,拿到数据跳转到另一个页面,于是我鬼使神差的写下了这一段代码

dart 复制代码
void main(){
  print("初始化");
  refreshData();
  gotoNextPage('路由',state);
}

写的时候我是这样想的,refreshData调用readDataBase,这里await了,那么refreshData肯定也会阻塞在这里,等await到了结果,然后再去跳转,一切都是那么的完美,等运行的时候就来问题了,发现调用gotoNextPage的时候拿不到数据。 经过了一个小时的调试之后,最终定位到了问题,就是在refreshData函数里面,await readDataBase();这句代码其实是不会阻塞refreshData的调用方的,因为我们没有在调用refreshData时await,当我们执行await readDataBase();这句代码,当前函数会立即返回一个Future,只是这个Future没有结果,想到这就很解决这个问题了,就是在调用refreshData的时候await一下就好。

例子

csharp 复制代码
Future<void> main() async {
  print("开始程序");
  f1();
  print("结束main");
}

Future<void> f1() async {
  await Future.delayed(Duration(seconds: 3));
  print("222");
}


//结果是
开始程序
结束main
222

总结

在调用异步函数的时候需要仔细check需不需要await,以前一直觉得await会阻塞住函数,原来await其实是会立即返回一个Future对象的,如果调用方没有await这个future的结果,那么调用方还是会继续往下执行,等future结果回来了,await之后的代码才会继续执行。

相关推荐
装不满的克莱因瓶2 天前
【2026 持续更新】Flutter 零基础到精通全攻略(一)
flutter·app·dart·移动端
JMchen12314 天前
跨技术栈:在Flutter/Compose中应用自定义View思想
java·经验分享·flutter·canvas·dart·自定义view
LawrenceLan18 天前
37.Flutter 零基础入门(三十七):SnackBar 与提示信息 —— 页面反馈与用户交互必学
开发语言·前端·flutter·dart
LawrenceLan19 天前
36.Flutter 零基础入门(三十六):StatefulWidget 与 setState 进阶 —— 动态页面必学
开发语言·前端·flutter·dart
天意__19 天前
鸿蒙(ArkTS)与Flutter(Dart)开发语法全面对比
flutter·华为·harmonyos·arkts·dart·arkui
眼眸流转19 天前
Flutter学习笔记(三)
flutter·dart
LawrenceLan19 天前
38.Flutter 零基础入门(三十八):网络请求实战 http、dio —— 获取列表与刷新 UI
开发语言·前端·flutter·dart
LawrenceLan1 个月前
30.Flutter 零基础入门(三十):GridView 网格布局 —— 九宫格与商品列表必学
开发语言·前端·flutter·dart
LawrenceLan1 个月前
31.Flutter 零基础入门(三十一):Stack 与 Positioned —— 悬浮、角标与覆盖布局
开发语言·前端·flutter·dart
浩辉_2 个月前
Dart - 内存管理与垃圾回收(GC)深度解析
flutter·dart