在Dart中是否允许在for循环中使用await?

53

我有一个类似以下代码的程序:

main() async {
  ooClass = new OoClass(1);
  int val = await function1();
  print(val);
  ooClass = new OoClass(2);
  val = await function1();
  print(val);
  ooClass = new OoClass(3);
  val = await function1();
  print(val);

}

OoClass ooClass;

Future<int> function1() async {
  List list3 = await function2();
  return list3.indexOf('Ok');
}


Future<List<String>> function2() async {

  List<String> list1 = new List<String>();

  function3(Map<String, int> map1) async {
    String string1 = '';
    bool bool1 = false;
    List<String> list2 = [];
    String string2;

    function4(String string3) async {
      if (ooClass.function7(string3)) return;
      if (ooClass.function8() && !bool1) {
        bool1 = true;
        return;
      }
      string2 = await function5(string3);
      list2.add(string2);
    }

    for (String key in map1.keys) {
      await function4(key);
    }
    string1 = list2.join(', ');
    list1.add(string1);
  }

  for (Map<String, int> idxList in ooClass.function6()) {
    await function3(idxList);
  }
  return list1;
}

function5(String s1) {
  return new Future.value('Ok');
}

class OoClass {

  List<Map<String, int>> map2;
  bool bool3 = false;

  OoClass(int type) {
    switch(type) {
      case 1:
        map2 = [{'Ok':1}];
        break;
      case 2:
        map2 = [{'id': 1, 'Ok':1}];
        break;
      case 3:
        map2 = [{'foo': 1, 'Ok':1}];
        bool3 = true;
        break;
    }
  }

  List<Map<String, int>> function6() {
    return map2;
  }

  bool function7(String string9) {
    if (string9 == 'id') return true;
    return false;
  }

  bool function8() {
    return bool3;
  }
}

这段代码完美运行。

但在实际环境中,当调用await function4(key);时,function2返回list1 List(为空)。Function4调用稍后执行,但是function2的结果丢失了。

我真的不理解这种行为。它可能是一个错误或者不能在for循环中使用await?如果不能在for循环中使用await,我该如何以另一种方式实现?

我正在使用dart 1.22.0-dev.4,但我也尝试过更旧(和稳定)的版本,结果相同。


我最终找到了问题,并不是由于在for循环中使用await引起的。而是我的代码出错了。


2
for 中使用 await 是可以的。你的代码示例太复杂了,不值得进一步调查。 - Günter Zöchbauer
2个回答

82

是的,在Dart中,await可以在for循环内部使用,并且它会按预期工作。

for (var o in objects) {
  await doSomething(o);
}

如果这就是您要寻找的内容,甚至可为流使用await for

await for (var event in eventStream) {
  print("Event received: $event");
}

你的示例在DartPad中能够正确运行。它太复杂和抽象了,难以调试,但至少从表面上看应该是可行的。但你说这段代码在你的“真实环境”中并不起作用。如果你能解释一下具体是什么意思,或许我们可以提供帮助。

另一个提示:充分利用静态分析,特别是使用await_only_futuresunawaited_futures规则。这可以帮助你捕获许多错误。


如果await doSomething(o);里面还有另一个await怎么办?顺便说一下,在我的情况下它不起作用。 - Rahul Vyas

68

List.forEachFuture.forEach

如果你正在使用.forEach()在一个List上,这是行不通的:

someList.forEach((item) async {
  await longFunc(item);
)}

你需要使用:

await Future.forEach<SomeType>(someList, (item) async {
  await longFunc(item);
});

我错误地认为这适用于List.forEach,直到找到this answer

示例

根据评论:如有需要,请添加List类型

  List<String> names = ['billy', 'joe'];
  
  Future.forEach<String>(names, (name) async {
    await Future.delayed(const Duration(milliseconds: 200));
    print(name);
  });

9
иҜ·жіЁж„ҸпјҢиҷҪ然иҝҷжҳҜжңҖдҪіж–№жі•пјҢдҪҶзј–иҜ‘еҷЁдёҚдјҡеңЁд»Јз Ғеқ—дёӯзҹҘйҒ“itemзҡ„зұ»еһӢгҖӮеӣ жӯӨпјҢдҪ еҸҜиғҪйңҖиҰҒи°ғз”Ёawait Future.forEach<TypeOfSomeList>(someList, (item) async {гҖӮ - David Chopin
1
谢谢@DavidChopin - 我遇到了一个错误,像这样The property 'property' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!').因为我没有以这种方式指定类型,而无论默认值是什么都可能为空...如果我之前没有看到你在这里整理代码的建议,我想这需要很长时间才能解决。添加此评论以防万一SEO将其他人带到这里。 - Turkey

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