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_asyncare 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_asyncfunction supportedIf 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
Also Liked
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
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
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.
Popular in Proposals: Ideas
Other popular topics
Latest Phoenix Threads
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









