View Source Rephex.AsyncActionMulti (rephex v0.1.1)
Manages multiple asynchronous operations under a specified map in Phoenix LiveViews,
extending Rephex.AsyncAction
capabilities.
Rephex.AsyncGroupAction
builds upon the foundation of Rephex.AsyncAction
by introducing the management of multiple AsyncResult
instances within a single, specified map.
This module is designed for scenarios where concurrent asynchronous tasks need to be executed and monitored within the same LiveView component, offering granular control over each task's lifecycle and state.
Example:
# AsyncAction need Rephex state.
defmodule RephexPgWeb.State do
alias Phoenix.LiveView.AsyncResult
@initial_state %{
count: 0,
# AsyncActionMulti requires map will contain AsyncResult.
delayed_add_multi: %{}
}
use Rephex.State, initial_state: @initial_state
def add_count(socket, %{amount: amount} = _payload) when is_integer(amount) do
update_state_in(socket, [:count], &(&1 + amount))
end
end
# Minimal implementation
defmodule RephexPgWeb.State.DelayedAddAsync do
alias RephexPgWeb.State
use Rephex.AsyncActionMulti, result_map_path: [:delayed_add_multi]
@impl true
def start_async(_state, _path, %{amount: amount} = _payload, _progress) do
:timer.sleep(1000)
amount
end
@impl true
def after_resolve(socket, _result_path, result) do
case result do
{:ok, amount} ->
socket
|> State.add_count(%{amount: amount})
{:exit, _reason} ->
socket
end
end
end
# Usage in LiveView
defmodule RephexPgWeb.AccountLive.Index do
alias RephexPgWeb.State
use RephexPgWeb, :live_view
use Rephex.LiveView
alias Phoenix.LiveView.AsyncResult
@impl true
def mount(_params, _session, socket) do
{:ok, socket |> State.init()}
end
@impl true
def handle_event(
"start_delayed_add",
%{"multi_key" => key, "amount" => amount},
socket
) do
{am, _} = Integer.parse(amount)
{:noreply, socket |> State.DelayedAddAsync.start(key, %{amount: am})}
end
def start_delayed_add_button(assigns) do
~H"""
<button
class="border-2"
phx-click="start_delayed_add"
phx-value-amount={@amount}
phx-value-multi_key={@multi_key}
>
<%= @text %>
</button>
"""
end
@impl true
def render(assigns) do
~H"""
<div class="border-2 m-5">
<div class="underline">AsyncActionMulti Example</div>
<div>We can run multiple async actions with the same module.</div>
<%= for i <- 1..3 do %>
<%= ~s{(AsyncResult is at [:delayed_add_multi, "key-#{i}"])} %>
<.start_delayed_add_button
amount={i}
multi_key={"key-#{i}"}
text={"Start delayed add #{i} by key-#{i}"}
/>
<% end %>
</div>
"""
end
end