【问题标题】:Async await not behaving properly异步等待行为不正常
【发布时间】:2020-09-02 23:15:35
【问题描述】:

试图弄清楚为什么它没有按照我期望的顺序执行。我希望 2 是最后一个执行的,但它在其他所有内容完成运行之前完成。 不明白为什么它在 4 之后和收听流之前返回函数。

Future mainFn() async {
    print('Listen 1');
    Ob o = await listenFn();
    print('Listen 2');
    return await someFn(o);
  }

Future<Ob> listenFn() async {
    o = new Ob();
    print('Listen 3');
    Stream<Ct> stream = await getCt();
    print('Listen 4');
    stream.listen((Ct _ct) {
      print('Listen 7');
      if (!cts.contains(_ct)) {
        setState(() {
          cts.add(_ct);
        });
      }
    }, onError: (a) {
      print('Listen 8');
      print(a);
    }, onDone: () async {
      print('Listen 9');
      o = await addOb(cts); <-- This function returns Future<Ob>
    });
  await stream.drain();
  print('Listen 14');
  return o;
  }

Future<Stream<Ct>> getCt() async {
  print('Listen 5');
  final String url = 'API_URL';
  final client = new http.Client();
  final request = http.Request('get', Uri.parse(url));
  final streamedRest = await client.send(request);
  print('Listen 6');
  return streamedRest.stream
      .transform(utf8.decoder)
      .transform(json.decoder)
      .map((data) => Helper.getData(data))
      .expand((data) => (data as List))
      .map((data) {
    return Ct.fromJSON(data);
  });
}

我来了

I/flutter (22211): Listen 1
I/flutter (22211): Listen 3
I/flutter (22211): Listen 5
I/flutter (22211): Listen 6
I/flutter (22211): Listen 4
I/flutter (22211): Listen 2
I/flutter (22211): Listen 7 <-- 4 Ct items in the stream
I/flutter (22211): Listen 7
I/flutter (22211): Listen 7
I/flutter (22211): Listen 7
I/flutter (22211): Listen 9
I/flutter (22211): Listen 10 <-- added more of these along the way
I/flutter (22211): Listen 11
I/flutter (22211): Listen 12
I/flutter (22211): Listen 13

【问题讨论】:

    标签: dart


    【解决方案1】:

    这是一个细分:

    1. 输入mainFn,打印Listen 1
    2. mainFn 呼叫并等待 listenFn
    3. 输入listenFn。打印Listen 3
    4. listenFn 呼叫并等待 getCt
    5. 输入getCt。打印Listen 5
    6. getCt 呼叫并等待 client.send
    7. client.send 完成工作并返回。
    8. getCt 恢复并打印Listen 6
    9. getCt 返回 Stream
    10. listenFn 恢复并打印Listen 4
    11. listenFnStream 添加一个监听器。
    12. listenFn 不返回任何内容
    13. mainFn 恢复并打印Listen 2
    14. mainFn 呼叫并等待 someFn
    15. Stream 发出事件,触发侦听器回调。
    16. 监听器回调为每个事件打印Listen 7
    17. Stream 最终完成并打印出Listen 9

    你出错的地方是你期望listenFn 将返回onDone 回调的结果。 listenFn 不等待 Stream 运行完成;它注册一个回调并立即返回。如果您在代码上运行 dartanalyzer,您应该会收到一条警告,指出 listenFn 被声明为返回一个值,但从不返回任何内容。

    【讨论】:

    • 现在说得通了。我如何让它等待stream.listen?添加 await stream.listen 什么都不做。
    • Stream.listen 只是注册回调,这是同步发生的。无需等待,因此它不会返回 Future。您必须等待 Stream 本身完成。有很多方法可以做到这一点,但最合适的可能是await stream.drain();
    • 谢谢,这很有帮助,正是我想要的。 await stream.drain 似乎在阻止返回。但是现在即使执行了 onDone 函数,该行之后的所有内容也不会执行。
    • 你是说Listen 2不打印?听起来您正在等待永远不会完成的Future。请注意,您仍然需要解决 listenFn 未返回您想要的值的问题(您尝试从 onDone 执行此操作,但 onDone 回调无法返回值)。
    • 我在 await.drain 和永远不会打印的 return 之间添加了一条线。 await stream.drain(); print('Listen 14'); return o; 而且 Listen 2 也不见了。我把它放在 onDone 括号外的 main 函数中。
    【解决方案2】:

    因此,如果将来有人偶然发现此问题,我会偶然找到解决此问题的方法。答案是使用await for

    stream.listen() 设置事件到达时将放入事件队列的代码,然后执行以下代码。

    等待事件之间的暂停,并一直这样做,直到流完成,所以在它发生之前不会执行后面的代码。

    await for(String s in stream) { print(s); }
    

    信用:https://stackoverflow.com/a/42613676/12689749

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      • 2016-03-25
      • 2017-10-09
      相关资源
      最近更新 更多