【问题标题】:flutter: How to correctly use async and await to freeze and wait for certain function finish before executing next line of code颤振:如何正确使用异步和等待冻结并等待某些功能完成,然后再执行下一行代码
【发布时间】:2021-03-09 18:10:20
【问题描述】:

我正在阅读async-await 文档并尝试使用它来使函数等待返回。根据我的理解(我是异步的新手),async 函数在第一个 await 关键字之前逐行执行,但在下面的代码中我不能这样做。我怎样才能做到这一点?

  List<Map> testinglist = [];
//function that obtain data somwhere and where I want to work on
  Future<void> _getEventData() async {
    testinglist.clear();
    debugPrint('right after clear');
    print(testinglist.length);
//await here to get the return from database
    var snapshot2 = await fireBaseDB.child('event').once();
    Map map2 = snapshot2.value;
//Problem here: I used await here, so I supposed line after this execute only after this is finished?
    await map2.keys.toList().forEach((element) {
      fireBaseDB
          .child('event')
          .child(element)
          .once()
          .then((DataSnapshot innersnapshot) {
        testinglist.add(innersnapshot.value);
        debugPrint('after entering');
        print(testinglist.length);
      });
    });
    debugPrint('end entering');
    print(testinglist.length);
    debugPrint('end');
  }

  @override
  Widget build(BuildContext context) {
  ...
              new RaisedButton(
                child: new Text("print data"),
                onPressed: () {
                  debugPrint('before entering');
                  print(testinglist.length);
                  _getEventData();
                },
              new RaisedButton(
                child: new Text("check length"),
                onPressed: _checkingLength,
                color: Colors.redAccent,
              ),
  ...
  }

The output isn't as I expected:
I/flutter (11527): before entering
I/flutter (11527): 3
I/flutter (11527): right after clear
I/flutter (11527): 0
I/flutter (11527): end entering
I/flutter (11527): 0
I/flutter (11527): end
I/flutter (11527): after entering
I/flutter (11527): 1
I/flutter (11527): after entering
I/flutter (11527): 2
I/flutter (11527): after entering
I/flutter (11527): 3

为什么after entering 不在end entering 之前?我理解 async 和 await 错误吗?我该如何解决这个问题

【问题讨论】:

    标签: flutter asynchronous async-await


    【解决方案1】:

    您可以通过两种方式实现您的目标:

    1. 使用Future.forEach 并等待innersnapshot - 如下所示:
    await Future.forEach(map2.keys.toList(), (element) async {
      final innersnapshot = await fireBaseDB
        .child('event')
        .child(element)
        .once();
      testinglist.add(innersnapshot.value);
      debugPrint('after entering');
      print(testinglist.length);
    });
    
    1. 通过将foreach 循环更改为for 循环,因为foreach 不是异步函数的最佳选择(对其他人来说可读性较差)。在 for 循环中,innersnapshot 也可以使用 await。

    所以改变:

        await map2.keys.toList().forEach((element) {
          fireBaseDB
              .child('event')
              .child(element)
              .once()
              .then((DataSnapshot innersnapshot) {
            testinglist.add(innersnapshot.value);
            debugPrint('after entering');
            print(testinglist.length);
          });
        });
    

    到:

    for (var element in map2.keys.toList()) {
      final innersnapshot = await fireBaseDB
        .child('event')
        .child(element)
        .once();
      testinglist.add(innersnapshot.value);
      debugPrint('after entering');
      print(testinglist.length);
    }
    

    【讨论】:

    • 非常感谢您的帮助,第二个有效,但不是第一个,它仍然以错误的顺序执行(与我的代码相同的输出)。我会尝试更多,看看是什么问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 2020-09-01
    • 2013-05-07
    相关资源
    最近更新 更多