munksgaard

munksgaard

Support async operations with liveview streams

I’m copying and pasting this issue from @Terbium-135 here verbatim, because I would be interested in such a feature as well, and because I don’t see any discussion about it on this forum.

The new async functions around assign_async are very nice! Easy to setup and a good enhancement to phoenix liveview functionality.

In my opinion it is very likely that these functions will be used for database queries, which might or might not return a greater amount of data for the initial rendering.

Since the general recommendation is to use streams (which are also a great improvement and simplification) I would like to see a stream_async function supported

If this is not the proper place to ask for this: feel free to delete/close this issue

Sincerely

In short, now that we have assign_async, it seems natural (to me) that we should also have stream_async.

Is there any particular reason why stream_async is not implemented at the moment, or is it more a question of bandwidth?

Marked As Solved

munksgaard

munksgaard

Since 1.1.5 stream_async/4has been part of LiveView. See also #3944.

Also Liked

quetz

quetz

Hello,

I provided a hex package live_stream_async with which provides you with stream_async/4 macro that you can use like this:

  use LiveStreamAsync

  def mount(%{"location" => location}, _, socket) do
    {:ok,
     socket
     |> stream_async(:hotels, fn -> Hotels.fetch!(location) end)
    }
  end
munksgaard

munksgaard

I finally got around to try and implement this using start_async/3 and handle_async/3. It turns out to be rather simple to do, so perhaps it’s not worthy of a macro at all.

Because streams must be lists, I needed to add an extra assign to control whether or not the stream had been asynchronously loaded. Here’s what I did:

@impl true
def mount(%{"id" => id}, _session, socket) do
  {:ok,
   socket
   |> assign(:foos, AsyncResult.loading()),
   |> stream(:foos, [])
   |> start_async(:foos, fn ->
     Foo.list_foos(id)
   end)}
end

@impl true
def handle_async(:foos, {:ok, foos}, socket) do
  {:noreply,
   socket
   |> assign(foos: AsyncResult.ok(:ok))
   |> stream(:foos, foos, reset: true)}
end

@impl true
def render(assigns) do
  ~H"""
  <.async_result :let={_foos} assign={@foos}>
    <:loading>
      <div><%= gettext("Loading...") %></div>
    </:loading>
    <:failed :let={_failure}>
      <div><%= gettext("An error occurred.") %></div>
    </:failed>
    <.table id="foos" rows={@streams.foos}>
      ...
    </.table>
  </.async_result>
  """
end
josevalim

josevalim

Creator of Elixir

assign_async is implemented on top of start_async and the handle_async callback. So you could use those to build your own asynchronous behavior and add to the stream in the callback.

Where Next?

Popular in Proposals: Ideas Top

hst337
Elixir compiler and language specification Purpose of the proposal Elixir language is in mature state and no breaking or heavy changes ar...
New
c4710n
This is an idea for improving the workflow of iex -S mix phx.server The Problem and The Solution in use When running multiple Phoenix en...
New
rmoorman
Current situation Currently, the structure of the HTML returned by phoenix is determined by the layouts (components/layouts/[root,app].ht...
New
dkuku
This is a proposal to make the map key mismatch errors a bit better: Every time I have a typo It’s very challenging for me even when I u...
New
bartblast
This could resolve to {[a: 1, b: 2]}. Was it ever considered to allow such syntax? Notice this: {:abc, a: 1, b: 2} and this: my_fun(:abc,...
New
byhemechi
Many web frameworks (e.g. Remix, Gatsby) have an option for their link components that begins the navigation request on hover so that whe...
New
eagle-head
Hi everyone, I’ve been researching Content Security Policy Level 3 support in Phoenix and wanted to share my findings and a proposal for...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54921 245
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement