2017-02-21 9 views
0

Как работает Elixir Enum.map([Task.t], &Task.await)?Как работает Enum.map с 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] 
  1. Я бы ожидать, что второй "starting new task" показал перед "done async 2" сделал. Как он выполнял все асинхронные задачи с нетерпением?
  2. От doc он говорит, что await будет «Ожидает ответ задачи и возвращает его». Я предположил, что это означает, что он приостановит процесс вызова, пока сообщение завершения не будет отправлено обратно из процесса Task. Если это так, он должен приостановить на каждом вызове Task.await(Task.t) в каждой итерации map и никогда не выполнять эти задачи одновременно. Журнал доказал, что мое предположение неверно. Но где это неправильно?

Вот мой РЕПЛ http://elixirplayground.com?gist=f1fa90eadc00441a360d8bc883d64529

ответ

4

Task.async не ждет, пока Task.await для запуска функции, переданные ему; он начинает запускать его мгновенно. Работа, заданная здесь, очень мала, и поэтому оба из них уже закончены, исполняя ее к моменту, когда Enum.map получает шанс ждать второй задачи.

0

Благодарим @Dogbert за просвещение. Я неправильно понял 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) } 

В эликсира, Task.async будет выполнять функцию в новом процессе, который похож на start_link. И await только ждет, пока процесс выполнения вернет результаты.

Не сказать, что дизайн необоснован. Но я бы предпочел, чтобы они назвали это чем-то другим, чем async, потому что это нарушает соглашения с другими распространенными языками, поэтому их труднее изучить.

Смежные вопросы