来自golang和c#的elixir中函数的并行或异步任务

I am learning Elixir with Phoenix. I built a few REST API servers, easily, but there is one more requirement that I need to implement. I need to be able to do parallel or async tasks to call/execute some API from the Backend, and put those results to a JSON response.

This is how I would implement it roughly from Go and C#

// Golang
userCount := make(chan int)
usersList := make(chan []Users)

go getAggregateUserCounts(userCount)
go getGetUsersList(usersList)

// do other heavy tasks from here

httpJsonResponse(map[string]interface{}{
    "test":       1,
    "user_count": <-userCount,
    "users_list": <- usersList ,
})



// C# or dotnetcore
public async Task<JsonResult> GetJson(string dbName, string collection)
{
    using(var client = new MongoDBCon())
    {
        // some heavy computations
        var documents = await col.FindAsync<Users>(FilterDefinition<Users>.Empty);
        return Json(new {
              users_count: await documents.ToListAsync().Result.Count,
              users: await users.GetusersList()
        });
    }
}

So far, this is what I have for elixir:

// Elixir
def start do
  IO.puts "starting.."
  response = %{}
  1..3
  |> Enum.map(fn(id) -> async_get_request(id) end)
  |> Enum.each(
    fn(_) -> 
      item = get_result()
      IO.inspect :"#{item[:user][:id]}"
      IO.inspect item[:user]

      # Map.put(response, :"#{item[:user][:id]}", item[:user])
    end)

  IO.puts "done.."
  IO.inspect response
end

def start2 do
  IO.puts "start2.."
  res = %{
    "item" => Task.async(fn -> IO.puts "weee" end) 
  }
end

def get_request(id) do
  sleep = :rand.uniform(10)
  :timer.sleep(sleep)  
  %{user: %{id: id, sleep: sleep}}
end  

def async_get_request(id) do
  caller = self()
  spawn(fn ->  
    send(caller, {:result, get_request(id)})  
  end)      
end

def get_result do
  receive do
    {:result, result} -> result
  end
end

the result is

iex(3)> Para.start
starting..
%{id: 2, sleep: 1}
%{id: 3, sleep: 3}
%{id: 1, sleep: 9}
done..
%{}

what I want is to have, is

%{
 id: 2, {id: 2, sleep: 1},
 id: 3, {id: 3, sleep: 3},
 id: 1, {id: 1, sleep: 9}
 }

The above example is just for learning or practice, but for real world, I would prefer adding values to the map by some parallel tasks.

I'm not sure if this is even possible with elixir.

 %{
    "users_count": AsyncUsersModule.GetUsersTotal(),
    "users_list": AsyncUsersModule.GetUsersList()
 }

and response in json should be

{
  "users_count": 10000,
  "users_list": []
}

I know I still need lots of practice and reading, I just need some help.

I believe what you need is Task.yield_many/2 and Kernel.SpecialForms.for/1 to treat the result:

results = 
  1..3
  |> Enum.map(&Task.async(fn -> get_request(&1) end))
  |> Task.yield_many()

for { _, {:ok, value}} <- results, do: IO.inspect(value)