我正在编写某种机器人(命令行应用程序),当我使用“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
如果有人知道我做错了什么,我会很感激。
答案 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));