【问题标题】:Flutter : correct way to call "nested future"Flutter:调用“嵌套未来”的正确方法
【发布时间】:2021-08-18 09:33:17
【问题描述】:

在 Flutter 中调用嵌套未来的最佳方式是什么?还是一般的颤振?

在我的应用程序中,我必须获取 当前用户(其数据位于 final storage = new FlutterSecureStorage();

从这个用户,我调用了一个由 user id 提供的 API。这两个部分独立工作很好(很慢,但这是另一回事)。

在许多屏幕上,我必须调用异步函数,我使用Future.delayed 来执行此操作,而我的同事习惯使用这样的东西:

  void initState() {
    super.initState();
    getCurrentUser();
  }

  void getCurrentUser() async {
    user = await UserAuth.getCurrentUser();
  }

这是我的嵌套期货。我需要在我的 initState 上加载当前用户来加载我的出版物。我必须在其中获取用户,因为它也可以是非当前用户(此功能将用于检索当前用户以及其他用户的出版物)。

class _UserPublicationsState extends State<UserPublications> {
  List<Publication> listPublications;
  List<Widget> list = [];
  User user;

  @override
  void initState() {
    super.initState();
    Future.delayed(Duration.zero, () async {
      await UserAuth.getCurrentUser().then((value) {
        setState(() {
          user = value;
          UserWS.getPublicationsPerUsers(user).then((value) {
            setState(() {
              listPublications = value;
            });
          });
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    if (listPublications == null) {
      return FullPageLoading();
    }

    String title = "title";

    return SafeArea(
      child: Scaffold(
        appBar: getSimpleAppBar(context, title),
        body: SingleChildScrollView(
          child: getSavedPublications(),
        ),
      ),
    );
  }
}

【问题讨论】:

  • 1.我不明白“调用嵌套的未来”是什么意思。你等待Futures。等待Future 可能涉及在内部等待中间Futures,但这是等待者需要关注的实现细节。 2. 完全不清楚你为什么使用Future.delayed。如果只是创建一个async 函数,那不是很有用。 3. 你通常应该只使用FutureBuilder。另请参阅:What is a Future and how do I use it?
  • 1) 通过嵌套,我理解“未来取决于另一个未来结果”。 2)我正在使用Future.delayed,因为这就是我学会使用未来的方式。 3) 我可以在一个 raw 中使用 2 个 FutureBuilder 吗?
  • 2.使用Future.delayed 处理现有的Future 毫无意义。为什么不使用Future.delayed 来使用Future.delayed 返回的Future?为什么不无限调用Future.delayed? 3. 我不明白“in a raw”是什么意思。
  • 2) 我不明白,你能给我举个例子吗? 3)我的意思是:首先,获取用户;第二;让该用户调用另一个未来方法

标签: flutter nested future setstate


【解决方案1】:

我不确定你的方法是什么,但你可以将你的未来放在 Future.wait() 中的列表中

像这样:

Future.wait([
      Future.delayed(Duration.zero),
      Future.delayed(Duration.zero),
    ]);

如果你的意思是一个未来依赖于另一个未来,你应该在未来调用之后使用 .then()

像这样:

Future.delayed(Duration.zero).then((value) => Future.delayed(Duration.zero));

我希望这就是你要找的东西

【讨论】:

    【解决方案2】:

    正如我在 cmets 中提到的,等待“嵌套的 Future”与等待任何其他 Future 没有什么不同。假设你有:

    Future<String> fetchDataFromServer() async {
      var firstPart = await fetchFoo();
      var secondPart = await fetchBar();
      return '$firstPart $secondPart';
    }
    

    调用者只需要做,比如说,print(await fetchDataFromServer());fetchDataFromServer 在内部等待其他一些 Futures 并不重要。 fetchDataFromServer 返回一个Future&lt;String&gt;,指示操作何时完成。调用者不需要知道也不关心该操作是否涉及其他异步子操作。

    我正在使用Future.delayed,因为这就是我学会使用未来的方式。

    Future.delayed 本身返回一个Future。如果您认为需要使用Future.delayed 来使用Future,那么合乎逻辑的结论是:

    var future = fetchDataFromServer();
    var future2 = Future.delayed(Duration.zero, () async => await future);
    var future3 = Future.delayed(Duration.zero, () async => await future2);
    var future4 = Future.delayed(Duration.zero, () async => await future3);
    // Ad infinitum.
    

    通常您会使用Future.delayed 来实际引入延迟,通常将同步操作视为异步操作以用于测试或演示目的。如果您已经有一个现有的Future,那么用Future.delayed(Duration.zero, () =&gt; await existingFuture) 包装它是没有意义的。直接使用existingFuture即可。

    最后,使用await 是设置.then() 回调的语法糖。混合使用 await.then() 充其量是不一致的,最坏的情况是令人困惑。

    await someFuture.then((value) => doSomething(value));
    

    相当于:

    var value = await someFuture;
    doSomething(value);
    

    综上所述,您的代码:

    @override
    void initState() {
      super.initState();
      Future.delayed(Duration.zero, () async {
        await UserAuth.getCurrentUser().then((value) {
          setState(() {
            user = value;
            UserWS.getPublicationsPerUsers(user).then((value) {
              setState(() {
                listPublications = value;
              });
            });
          });
        });
      });
    }
    

    相当于:

    Future<void> _updatePublications() async {
      var currentUser = await UserAuth.getCurrentUser();
      setState(() {
        user = currentUser;
      });
    
      var publications = await UserWS.getPublicationsPerUsers(user);
      setState(() {
        listPublications = publications;
      });
    }
    
    @override
    void initState() {
      super.initState();
    
      _updatePublications();
    }
    

    请注意,在简化版本中,您可能希望合并两个 setState 调用,以便仅在 userlistPublications 都更新后重新构建小部件。

    【讨论】:

      猜你喜欢
      • 2021-09-03
      • 2022-07-26
      • 1970-01-01
      • 1970-01-01
      • 2017-02-21
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多