You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何确保Blazor中OnInitializedAsync仅执行一次?当前判断方案失效

Blazor OnInitializedAsync 仅加载一次数据失效的解决方法

问题原因

你用tableLoading实例变量做判断无效,是因为每次组件重新初始化(比如路由跳转返回、父组件重渲染导致子组件重建)时,这个实例变量会被重置为默认值false,相当于判断逻辑根本没起到作用。

解决方案

1. 使用静态字段+线程锁(简单场景)

把加载状态改成静态变量,让所有组件实例共享这个状态,同时加锁避免并发问题:

private static bool _tableLoading;
private static readonly object _lockObj = new object();

protected override async Task OnInitializedAsync()
{
    lock (_lockObj)
    {
        if (_tableLoading)
        {
            return;
        }
        _tableLoading = true;
    }

    try
    {
        users = await userService.GetSome(1, userType);
        _total = await userService.GetCount(userType);
    }
    finally
    {
        lock (_lockObj)
        {
            _tableLoading = false;
        }
    }
    Console.WriteLine("OnInitializedAsync");
}

2. 服务层缓存数据(推荐)

把数据缓存逻辑放到单例的UserService里,组件直接拿缓存好的数据,不用管加载状态:

// UserService 示例(确保服务注册为单例)
public class UserService
{
    private List<User> _cachedUsers;
    private int _cachedTotal;
    private readonly object _lockObj = new object();
    private readonly YourDbContext _dbContext;

    public UserService(YourDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<List<User>> GetSome(int page, int userType)
    {
        lock (_lockObj)
        {
            if (_cachedUsers != null)
            {
                return _cachedUsers;
            }
        }

        // 实际数据库查询逻辑
        var users = await _dbContext.Users
            .Where(u => u.Type == userType)
            .ToListAsync();

        lock (_lockObj)
        {
            _cachedUsers = users;
        }
        return users;
    }

    public async Task<int> GetCount(int userType)
    {
        lock (_lockObj)
        {
            if (_cachedTotal != 0)
            {
                return _cachedTotal;
            }
        }

        var count = await _dbContext.Users
            .CountAsync(u => u.Type == userType);

        lock (_lockObj)
        {
            _cachedTotal = count;
        }
        return count;
    }
}

组件里直接调用即可,不用做加载状态判断:

protected override async Task OnInitializedAsync()
{
    // 服务会自动返回缓存数据,无需重复查询
    users = await userService.GetSome(1, userType);
    _total = await userService.GetCount(userType);
    Console.WriteLine("OnInitializedAsync");
}

3. 持久化组件状态(.NET 6+ 路由组件适用)

如果是路由组件,用PersistComponentState特性保存状态,避免组件重建时丢失数据:

[PersistComponentState]
public partial class YourComponent
{
    private bool tableLoading;
    private List<User> users;
    private int _total;

    [Inject] private IPersistentComponentState PersistentState { get; set; }
    private PersistingComponentStateSubscription _subscription;

    protected override void OnInitialized()
    {
        // 注册状态持久化回调
        _subscription = PersistentState.RegisterOnPersisting(PersistCurrentState);
        
        // 恢复之前保存的状态
        if (PersistentState.TryGetFromJson<List<User>>("cachedUsers", out var savedUsers))
        {
            users = savedUsers;
        }
        if (PersistentState.TryGetFromJson<int>("cachedTotal", out var savedTotal))
        {
            _total = savedTotal;
        }
    }

    private Task PersistCurrentState()
    {
        // 保存当前状态
        PersistentState.PersistAsJson("cachedUsers", users);
        PersistentState.PersistAsJson("cachedTotal", _total);
        return Task.CompletedTask;
    }

    protected override async Task OnInitializedAsync()
    {
        // 已有缓存数据直接返回
        if (users != null) return;

        if (tableLoading) return;
        tableLoading = true;
        
        users = await userService.GetSome(1, userType);
        _total = await userService.GetCount(userType);
        
        tableLoading = false;
        Console.WriteLine("OnInitializedAsync");
    }

    public void Dispose()
    {
        _subscription.Dispose();
    }
}

内容的提问来源于stack exchange,提问作者lyj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 19:36:17