如何在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
相关产品推荐
相关产品推荐

