dps57553 2018-09-12 07:04
浏览 11

来自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.

  • 写回答

1条回答 默认 最新

  • duan01203 2018-09-12 07:16
    关注

    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)
    
    评论

报告相同问题?

悬赏问题

  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私