Async Helpers Overview

Production-Ready in v1.0.8

Eliminate 74% of async boilerplate with built-in helpers that transform tedious patterns into one-liners!

What Are Async Helpers?

Async helpers are production-ready utilities that eliminate common boilerplate patterns in async state management. Instead of writing repetitive code for timers, loading states, error handling, throttling, and caching, you get concise, readable one-liners.

These helpers are built directly into StoreComponent<T>, so they're available immediately when you inherit from the base component.

Available Helpers

All five helpers provide significant code reductions while improving readability and maintainability:

Helper Eliminates Code Reduction Use Case
UpdateDebounced Timer management (17 lines → 1 line) 94% Search inputs, form validation
AsyncData<T> Loading/error state (20+ lines → 1 property) 95% API calls, data fetching
ExecuteAsync Try-catch boilerplate (12 lines → 5 lines) 58% Error handling, async operations
UpdateThrottled Throttle logic (22 lines → 1 line) 95% Mouse move, scroll events
LazyLoad Cache + deduplication (15+ lines → 2 lines) 85% Expensive operations, API caching

Quick Overview of Each Helper

1

UpdateDebounced - Debounced Search

Automatically debounces rapid state updates, perfect for search inputs and form validation.


<input @oninput="@(e => UpdateDebounced(s => s.SetQuery(e.Value?.ToString() ?? ""), 300))" />

Learn more about UpdateDebounced →

2

AsyncData<T> - Simple Async State

Replaces 20+ lines of loading/data/error state management with a single property.

// State definition
public record UserState(AsyncData<User> User);

// Component usage
@if (State.User.IsLoading) { <p>Loading...</p> }
@if (State.User.HasData) { <p>@State.User.Data.Name</p> }
@if (State.User.HasError) { <p>@State.User.Error</p> }

Learn more about AsyncData<T> →

3

ExecuteAsync - Automatic Error Handling

Eliminates try-catch boilerplate with automatic error handling and state transitions.

await ExecuteAsync(
    () => Service.LoadAsync(),
    loading: s => s with { Data = s.Data.ToLoading() },
    success: (s, data) => s with { Data = AsyncData.Success(data) },
    error: (s, ex) => s with { Data = AsyncData.Failure(ex.Message) }
);

Learn more about ExecuteAsync →

4

UpdateThrottled - High-Frequency Events

Throttles rapid events to a maximum frequency, ideal for mouse move and scroll handlers.

// Throttle mouse move to max once per 100ms
<div @onmousemove="@(e => UpdateThrottled(s => s.SetPosition(e.ClientX, e.ClientY), 100))">
    Mouse tracker
</div>

Learn more about UpdateThrottled →

5

LazyLoad - Automatic Caching

Provides automatic caching with expiration and request deduplication for expensive operations.

// Automatic caching with 5-minute expiration + request deduplication
var user = await LazyLoad(
    $"user-{userId}",
    () => UserService.GetUserAsync(userId),
    cacheFor: TimeSpan.FromMinutes(5));

// If 10 components call this simultaneously, only 1 API call is made!

Learn more about LazyLoad →

Complete Example: Combining All Helpers

Here's a real-world example that demonstrates all five async helpers working together in a product search component:

ProductSearch.razor
@page "/products"
@inherits StoreComponent<ProductState>

<!-- 1. Debounced search -->
<input @oninput="@(e => UpdateDebounced(s => s.SetQuery(e.Value?.ToString() ?? ""), 300))"
       placeholder="Search..." />

<!-- 2. Load with ExecuteAsync -->
<button @onclick="Search">Search</button>

<!-- 3. Display with AsyncData -->
@if (State.Products.IsLoading) { <p>Loading...</p> }
@if (State.Products.HasData)
{
    @foreach (var product in State.Products.Data)
    {
        <div @onclick="@(() => LoadDetails(product.Id))">@product.Name</div>
    }
}

@code {
    async Task Search() =>
        await ExecuteAsync(
            () => ProductService.SearchAsync(State.Query),
            loading: s => s with { Products = s.Products.ToLoading() },
            success: (s, data) => s with { Products = AsyncData.Success(data) }
        );

    async Task LoadDetails(int id)
    {
        // 4. LazyLoad with caching
        var details = await LazyLoad(
            $"product-{id}",
            () => ProductService.GetDetailsAsync(id),
            TimeSpan.FromMinutes(5));

        await Update(s => s.AddDetails(id, details));
    }
}
Best Practice

Combine async helpers for maximum benefit. This example reduces approximately 100+ lines of boilerplate to just 30 lines of clean, readable code.

Key Benefits

🚀

74% Less Code

Eliminate repetitive patterns and focus on business logic instead of infrastructure.

📖

More Readable

Intent is clear at a glance. No need to parse through timer management or error handling.

🛡️

Battle-Tested

Production-ready with comprehensive test coverage and proven in real-world applications.

Zero Setup

Built into StoreComponent<T>. Just inherit and start using immediately.

🎯

Type-Safe

Full IntelliSense support and compile-time checking for all helpers.

🔧

Composable

Mix and match helpers as needed. They work seamlessly together.

Next Steps

Explore each helper in detail to learn about specific use cases, patterns, and best practices: