elixir Enum.map([Task.t], &Task.await)
如何工作?
async_1 = Task.async(fn ->
IO.inspect("done async 1")
1
end)
async_2 = Task.async(fn ->
IO.inspect("done async 2")
2
end)
results = Enum.map([async_1, async_2], fn(task) ->
IO.inspect("starting new task")
IO.inspect(task)
Task.await(task)
end)
IO.inspect(results)
从上面的代码中,我得到了IO日志:
"starting new task"
"done async 1"
"done async 2"
%Task{pid: #PID<0.51.0>, ref: #Reference<0.0.0.78>}
"starting new task"
%Task{pid: #PID<0.52.0>, ref: #Reference<0.0.0.79>}
[1, 2]
- 我希望第二个
"starting new task"
出现在"done async 2"
之前。它如何热切地执行所有异步任务? - 在文档中,它说
await
将"等待任务答复并返回"。我以为这意味着将暂停呼叫者进程,直到从Task
进程发送终结消息为止。如果是这种情况,则应在每次map
迭代中的Task.await(Task.t)
调用中暂停,并且永远不会同时执行这些任务。日志证明我的假设是错误的。但是哪里错了?
这是我的repl http://elixirplayground.com?
Task.async
不要等到Task.await
运行传递的函数;它开始立即运行。在此处提供的任务的工作很小,因此当Enum.map
有机会等待第二个任务时,它们都已经完成了。
感谢@dogbert的启蒙。我误解了elixir中的Task.async
。
它使我感到困惑,因为在ES7和C#中,async
只是一个关键字,表明该功能将返回Promise
或Asyncable
。async
仅被指控定义" Async_function"。await
做两件事 - 执行并等待结果。即。
function async(action: fn): Promise
function await(async_action: Promise): ?Any { execute_and_wait(async_function) }
在Elixir中,Task.async
将在新过程中执行该功能,该过程类似于start_link
。await
仅等待执行过程返回结果。
并不是说设计是不合理的。但是我更喜欢他们称其为async
以外的其他东西,因为它打破了其他通用语言的惯例,因此更难学习。