是否有一种方法可以跳过太长的await?(Flutter)

5

我在主函数(main)中使用了async await关键字,这样用户就需要在启动画面等待一段时间后才能进入应用程序。

void main() async {

  await Firebase.initializeApp();

  String? x;
  await FirebaseDatabase.instance.ref().child("data").once().then((snapshot) {
     Map data = snapshot.snapshot.value as Map;
     x = jsonEncode(data);
  });

  return ChangeNotifierProvider<DataModel>.value(
     value: DataModel(data: x),
     child: MaterialApp()
  );
}

如果有用户进入应用程序时没有网络连接,他们将永远停留在启动画面上。如果有慢速网络连接的用户,他们将更长时间地停留在启动画面上。
因此,无论网络连接问题是什么,我想设置一个最多只能等待5秒的等待时间,如果超过这个时间,跳过该部分直接进入应用程序。

今天早些时候,当我在没有互联网连接的情况下测试once()时,它实际上抛出了一个错误:"Error: [firebase_database/unknown] Error: Client is offline."。请参见https://dev59.com/o7X3oIgBc1ULPQZFu29w#71459638以获取我的测试结果。 - Frank van Puffelen
@FrankvanPuffelen,是的,即使使用try-catch-finally.catchError(),也一直卡在启动画面上。我认为目前还没有解决方法来捕获互联网连接错误。timeout解决了我的问题。 - Kucing Malaya
2个回答

4
将Firebase的API调用作为参数传递给一个函数,使该方法返回Future。
Future<String?> getData() async {
await FirebaseDatabase.instance.ref().child("data").once().then((snapshot) {
     Map data = snapshot.snapshot.value as Map;
     return jsonEncode(data);
  });
}

然后在主方法中,使用你创建的方法添加一个超时时间

void main() async {

  await Firebase.initializeApp();

  String? x = await getData().timeout(Duration(seconds: 5), onTimeout: () { 
  return null };

  return ChangeNotifierProvider<DataModel>.value(
     value: DataModel(data: x),
     child: MaterialApp()
  );
}

如果你的 API 执行时间超过 5 秒,则会退出并返回 null。


谢谢!如果没有网络连接,也可以处理“超时”问题,因为我们无法捕获“无网络”错误。 - Kucing Malaya

1

您可以使用用户竞争条件或 Future.timeout。

使用 Future.any 进行竞争条件。

final result = await Future.any([
  YourFunction(),
  Future.delayed(const Duration(seconds: 3))
]);

在上述代码中,先完成的函数将返回结果,因此如果您的代码执行时间超过3秒,其他函数将会返回答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接