How to make async requests using HTTPoison?

Javascript libraries offer an “async” mode because if they don’t, then using them blocks everything. This isn’t a problem in Elixir. When a single process does a “receive” it simply blocks that process. Every other process (like other HTTP requests) are still able to happen. It’s conceptually like doing .then in javascript, but actually even better.

This is awesome because not only does it apply to IO, it even applies to CPU bound operations. If your process starts an infinite loop or starts doing a lot of math, it won’t block other processes. In javascript it will.

7 Likes

Try using GenServer for this.
My suggestion is as follows:

defmodule MyCustomizedClient do
    use GenServer
    use HTTPoison.Base

    def start_link(opts) do
      GenServer.start_link(__MODULE__, :ok, opts)
    end

    def fetch(my_custom_client_instance, endpoint) do
      GenServer.cast(my_custom_client_instance, {:fetch, endpoint}) # cast is asynchronous
    end

    def handle_cast({:fetch, endpoint}, _state) do # I don't see the need of a state, but feel free
      {:noreply, get(@url <> endpoint)}
    end

    def process_response_body(body) do
      # treat response body as you will
    end
    # maybe other GenServer or HTTPoison callbacks you find necessary
end

Not for the problem described here but a complementary tactic for How to not block but still appear synchronous to every caller: Building Non Blocking Erlang apps

3 Likes