Phoenix LiveView Async Assigns
From ElixirBlocks
Example
defmodule AppWeb.PageLive do
use AppWeb, :live_view
alias Phoenix.LiveView.AsyncResult
@impl true
def mount(_params, _session, socket) do
{:ok,
assign_async(socket, :number, fn -> {:ok, %{number: really_complicated_function()}} end)}
end
@impl true
def handle_event("generate_number", _, socket) do
{:noreply,
socket
|> assign(:number, AsyncResult.loading())
|> start_async(:get_random_number, fn -> really_complicated_function() end)}
end
@impl true
def handle_async(:get_random_number, {:ok, res}, socket) do
%{number: number} = socket.assigns
{:noreply, assign(socket, :number, AsyncResult.ok(number, res))}
end
def handle_async(:get_random_number, {:exit, _reason}, socket) do
%{number: number} = socket.assigns
{:noreply,
assign(socket, :number, AsyncResult.failed(number, "Failed to generate a number."))}
end
@impl true
def render(assigns) do
~H"""
<div class="flex justify-center items-center h-screen bg-gradient-to-r from-blue-500 to-purple-600">
<div class="text-center bg-white shadow-lg rounded-lg p-10">
<h1 class="text-4xl font-bold text-gray-800 mb-5">Random Number Generator</h1>
<!-- Display Area -->
<.async_result :let={number} assign={@number}>
<:loading>
<div
class="spinner-border animate-spin inline-block w-8 h-8 border-4 rounded-full text-blue-700"
role="status"
>
<span class="visually-hidden">Loading...</span>
</div>
</:loading>
<:failed :let={_reason}>
<div class="mt-5 text-red-500">
Failed to generate a number.
</div>
</:failed>
<div class="text-6xl font-bold text-green-600 mb-5">
<%= number %>
</div>
<button
phx-click="generate_number"
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out transform hover:scale-105"
>
Generate Random Number
</button>
</.async_result>
</div>
</div>
"""
end
def really_complicated_function() do
# Simulate a really complicated function, takes a long time to run and will fail sometimes
:timer.sleep(1000)
if Enum.random(1..10) > 5 do
:error
else
Enum.random(1..100)
end
end
end