List.forEach()中的异步/等待

时间:2017-02-26 11:02:45

标签: asynchronous dart

我正在编写某种机器人(命令行应用程序),当我使用“forEach”方法时,我遇到异步执行问题。 这是我正在尝试做的简化代码:

main() async {
  print("main start");
  await asyncOne();
  print("main end");
}

asyncOne() async {
  print("asyncOne start");
  [1, 2, 3].forEach(await (num) async {
    await asyncTwo(num);
  });
  print("asyncOne end");
}

asyncTwo(num) async
{
  print("asyncTwo #${num}");
}

这是输出:

main start
asyncOne start
asyncOne end
main end
asyncTwo #1
asyncTwo #2
asyncTwo #3

我想要的是:

main start
asyncOne start
asyncTwo #1
asyncTwo #2
asyncTwo #3
asyncOne end
main end

如果有人知道我做错了什么,我会很感激。

5 个答案:

答案 0 :(得分:18)

您需要使用Future.forEach。

main() async {
  print("main start");
  await asyncOne();
  print("main end");
}

asyncOne() async {
  print("asyncOne start");
  await Future.forEach([1, 2, 3], (num) async {
    await asyncTwo(num);
  });
  print("asyncOne end");
}

asyncTwo(num) async
{
  print("asyncTwo #${num}");
}

答案 1 :(得分:14)

我认为用forEach方法实现你想要的东西是不可能的。但是它可以使用for循环。实施例;

asyncOne() async {
  print("asyncOne start");
  for (num number in [1, 2, 3])
    await asyncTwo(number);
  print("asyncOne end");
}

答案 2 :(得分:7)

您无法使用ArgumentError: wrong number of arguments (given 3, expected 0) # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure/output_builder.rb:53:in `block in merge_strategy' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure/output_builder.rb:19:in `merge!' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure/output_builder.rb:19:in `add' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:62:in `block (2 levels) in serializable_value' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/base.rb:108:in `block in with_attr_path' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/options.rb:102:in `with_attr_path' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/base.rb:107:in `with_attr_path' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:60:in `block in serializable_value' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:59:in `each' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:59:in `each_with_object' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:59:in `serializable_value' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:61:in `block (2 levels) in serializable_value' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/base.rb:108:in `block in with_attr_path' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/options.rb:102:in `with_attr_path' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/base.rb:107:in `with_attr_path' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:60:in `block in serializable_value' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:59:in `each' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:59:in `each_with_object' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/exposure/nesting_exposure.rb:59:in `serializable_value' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-entity-0.6.1/lib/grape_entity/entity.rb:473:in `serializable_hash' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/formatter/json.rb:6:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/formatter.rb:44:in `block in build_formatted_response' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/formatter.rb:44:in `collect' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/formatter.rb:44:in `build_formatted_response' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/formatter.rb:28:in `after' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/base.rb:34:in `call!' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/base.rb:24:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/base.rb:31:in `call!' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/base.rb:24:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/base.rb:31:in `call!' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/base.rb:24:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/error.rb:34:in `block in call!' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/error.rb:33:in `catch' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/error.rb:33:in `call!' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/middleware/base.rb:24:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/rack-2.0.1/lib/rack/head.rb:12:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/endpoint.rb:224:in `call!' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/endpoint.rb:218:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/router/route.rb:72:in `exec' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/router.rb:119:in `process_route' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/router.rb:74:in `block in identity' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/router.rb:93:in `transaction' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/router.rb:72:in `identity' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/router.rb:57:in `block in call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/router.rb:135:in `with_optimization' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/router.rb:56:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/api.rb:119:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/api.rb:45:in `call!' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/grape-0.19.1/lib/grape/api.rb:40:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/rack-2.0.1/lib/rack/etag.rb:25:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/rack-2.0.1/lib/rack/conditional_get.rb:25:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/rack-2.0.1/lib/rack/head.rb:12:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/railties-5.0.1/lib/rails/rack/logger.rb:36:in `call_app' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/railties-5.0.1/lib/rails/rack/logger.rb:24:in `block in call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/railties-5.0.1/lib/rails/rack/logger.rb:24:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/rack-2.0.1/lib/rack/runtime.rb:22:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/rack-2.0.1/lib/rack/sendfile.rb:111:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/railties-5.0.1/lib/rails/engine.rb:522:in `call' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/rack-test-0.6.3/lib/rack/mock_session.rb:30:in `request' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/rack-test-0.6.3/lib/rack/test.rb:244:in `process_request' # /home/doimhneacht/.rvm/gems/ruby-2.3.1/gems/rack-test-0.6.3/lib/rack/test.rb:124:in `request' # ./spec/requests/contacts_spec.rb:39:in `block (4 levels) in <top (required)>' ,因为它实际上并未查看其回调的返回值。如果它们是期货,它们就会丢失,而不是等待它们。

您可以像Steven Upton建议的那样进行循环,或者如果您希望操作同时运行,则可以使用forEach,而不是一个接一个地运行:

Future.wait

答案 3 :(得分:1)

我知道这是一个老问题,但是我会在这里留下一个新的答案,希望这对以后的人有所帮助。

您可以使用forEach 来实现以下目的:

  asyncOne() async {
  print("asyncOne start");
  await Future.forEach([1, 2, 3],(num) async {
    await asyncTwo(num);
  });
  print("asyncOne end");
}

答案 4 :(得分:0)

要解决此问题,我们可以切换到 for..in 构造或使用 Future.forEach 方法

asynchronous代码中,我们应该进行错误处理 可以使用 dart 中的 try..catch 块处理异步代码中的错误。本质上,如果在 try 块内抛出错误,则可以使用 catch 块接收和处理此类错误。要做到这一点,请按照以下代码

void main() async {
  try
  {
    print("main start");
    await asyncOne();
    print("success!");
  }
  catch(e) {
    print("Looks like we caught an error: ${e.toString()}");
  }
}

asyncOne() async {
  print("asyncOne start");

  await Future.forEach([1,2,3], (num) async => await asyncTwo(num));
  
  print("asyncOne end");
  
}

asyncTwo(num) async
{
  print("asyncTwo #${num}");
}

Future.forEach() 在移动到下一个元素之前等待每个 Future 完成。

当您需要等待多个 Futures 完成而不管它们的顺序如何时,您可以像这样使用 Future.wait() 方法:

Future.wait([1, 2, 3].map(functionCall));