You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Dart同步函数中等待Future完成后再执行?

解决方案

核心结论

Dart的单线程事件循环机制决定了同步函数无法直接暂停等待Future完成——你的无效方案里的while循环会阻塞整个线程,导致Future的回调永远没有执行机会,自然无法完成初始化。正确的做法是调整启动流程,将同步的初始化逻辑改为异步,让应用等待数据库初始化完成后再启动。


具体实现步骤

1. 重构StorageService,改用异步工厂方法初始化

把构造函数改为私有,通过异步工厂方法确保_db完全初始化后再返回实例:

class StorageService {
  late Database _db;

  // 私有构造函数,禁止直接实例化
  StorageService._();

  // 异步工厂方法:初始化完成后才返回实例
  static Future<StorageService> create() async {
    final service = StorageService._();
    service._db = await service.initDb();
    return service;
  }

  Future<Database> initDb() async {
    if (Platform.isWindows || Platform.isLinux) {
      sqfliteFfiInit();
      databaseFactory = databaseFactoryFfi;
    }

    return openDatabase(
      join(await getDatabasesPath(), 'my.db'),
      onCreate: (db, version) => _createTables(db, version),
      version: 1,
    );
  }
}

2. 让依赖注入的配置方法变为异步

修改DependencyInjection.configure(),等待StorageService初始化完成后再注册服务:

class DependencyInjection {
  static final _services = <Type, Object>{};

  static Future<void> configure() async {
    // 等待StorageService初始化完成
    final storage = await StorageService.create();
    _services[StorageService] = storage;
    
    // 初始化其他依赖服务(比如DictionaryService)
    _services[DictionaryService] = DictionaryService(storage);
  }

  static T get<T>() => _services[T] as T;
}

3. 异步启动应用

将main函数改为异步,等待所有初始化完成后再调用runApp:

void main() async {
  // 等待初始化流程完成
  await setupBeforeRun();
  // 初始化完成后再启动应用
  runApp(const App());
}

Future<void> setupBeforeRun() async {
  await DependencyInjection.configure();
  // 确保DictionaryService的操作也等待完成
  await DependencyInjection.get<DictionaryService>().getDictionaries();
}

备选方案(无async main场景)

如果因为框架限制不能使用async main,可以通过Future链式调用实现:

void main() {
  setupBeforeRun()
      .then((_) => runApp(const App()))
      .catchError((error) {
        // 处理初始化失败的情况,比如显示错误页面
        print('初始化失败:$error');
        runApp(const ErrorPage());
      });
}

Future<void> setupBeforeRun() async {
  await DependencyInjection.configure();
  await DependencyInjection.get<DictionaryService>().getDictionaries();
}

为什么你的无效方案会挂起

Dart的事件循环分为微任务队列和事件队列,同步代码会优先执行。你的while循环是同步代码,会一直占用线程,导致Future的回调(then里的逻辑)永远无法进入队列执行,所以isNotComplited永远不会变为false,应用彻底卡死。

内容的提问来源于stack exchange,提问作者Krzysztof

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:52:41