Things I Learned using Phoenix LiveView in 2024 (Part 2)

The beauty of assign_async/3 and async_result/1

# LiveView 
def handle_params(params, _uri, socket) do
         # ... more assigns here
         |> assign_async_coffees()}

# ... more code here

defp assign_async_coffee(socket) do
    assign_async(socket, :coffees, fn -> 
        {:ok, %{coffees: Coffee.load_more_coffees}}

    It allows the user to get a working UI quickly while the system fetches some data in the background or talks to an external service, without blocking the render or event handling

  • What I liked about the beauty of using assign_async/3 is that everything is asynchronous. I get the chance to process data without blocking the render or event handling

  • I also have the chance to handle different states like the loading, failures and the successful result

    You also want to catch any errors or exits and translate it to a meaningful update in the UI rather than crashing the user experience.

  • And just in case there will any exit errors, I will be able to handle that in the liveview and show it nicely for my users.

The built-in component

# LiveView heex file
<.async_result :let={coffees} assign={@coffees}>
    <:loading>Preparing what are the best coffees for you...</:loading>
    <:failed :let={_failure}>Please be patient, something came up...</:failed>
    <div :for={coffee <- coffees}>
        Here is your coffee <%= coffee %>
  • assign_async/3 has a partner so called async_result/1 that I could say a built-in partner wherein you can use it to render the different states that you want to show to your users.

  • it is a functional component.

  • You can even customize the loading and failed component slots to have an even more beautiful UI.

From there on, users can choose nicely from the list of coffees from your application if you seamlessly implemented this kind of approach.

But I wonder, does using this one have any drawbacks?

That's another thing to find out.

Happy coding