Blazor-防止双重HTTP调用并等待第一个

问题描述

在我的Blazor应用程序(WebAssembly)中,我需要在ApplicationState中加载用户数据。 我的许多页面都需要此User数据,因此在其OnAfterRenderAsync方法上,如果未加载User数据,我将加载它:

pathVariable

但是,如果我快速转到另一个页面,则用户数据将不会被加载,并且页面会询问新的请求。

因此,我想等待是否已有请求,而不是开始新的请求。

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        loadingSession = true;
        if (!sessionState.UserDataLoaded)
            await sessionState.LoadUserData();
        loadingSession = false;

    }
    await base.OnAfterRenderAsync(firstRender);
}

我尝试了许多事情,例如TaskResetEvent,Task中的Thread.Sleep,...但是我无法正确地做到这一点。 最好的方法是什么?

解决方法

OnAfterRenderAsync 和OnAfterRender在组件完成渲染之后被调用。

OnInitializedAsync 和OnInitialized在组件初始化之后被调用 从其父组件中接收到其初始参数 SetParametersAsync。

将代码移至OnInitializedAsync方法将在呈现控件之前加载用户数据。

编辑:(您要在组件之间传递状态

Microsoft documentation on State Management

将状态保存在内存中并通过依赖注入将其传递给组件的另一个示例。

要使用“状态管理”,您必须注册一个可用于状态管理的“服务”。

例如;创建一个名为AppState的类,其中包含您要保持其状态的值。

public class AppState
{
    public AppState()
    {
        //this class is to help maintain application state.
    }

    public UserData UserData { get; set; }

    public string SomeOtherStateValue { get; set; }
}

然后在您的Services中将此类注册为Singleton(请参见Service Lifetimes):

public static async Task Main(string[] args)
{
    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.RootComponents.Add<App>("app");
    builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
   //...other services
   //...

   // add AppState as singleton
    builder.Services.AddSingleton<AppState>(); 

   //...
   //...more stuff
    await builder.Build().RunAsync();
}

然后在您的Index.razor文件中(或您第一次需要调用的地方)使用依赖注入来访问AppState和{{ 1}}使用OnInitialzedAsync()调用用户数据。

HttpContent

这将等待对API的调用,直到收到响应为止。 如果响应成功,即:@page "/" @using System.Text.Json @using System.Text @inject AppState appState @inject HttpClient httpClient <h1>..all your html or components on the page...</h1> @code{ protected override async Task OnInitializedAsync() { var userRequestData = new UserDataRequest(options); var request = new StringContent(JsonSerializer.Serialize(userRequestData),Encoding.UTF8,"application/json"); var response = await httpClient.PostAsync($"api/users/",request); if (response.IsSuccessStatusCode) { appState.UserData = await JsonSerializer.DeserializeAsync<UserData>(await response.Content.ReadAsStreamAsync(),new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); } await base.OnInitializedAsync(); } } 为真。从响应消息中提取数据并将其存储在response.IsSuccessStatusCode中。

在任何后续组件中,您可以使用appState.UserDate通过注入来获取AppState,或者如果它位于代码文件@inject AppState appState

中,

在随后的组件中,您可以在[Inject] AppState appState;方法中添加一个检查:

OnInitializedAsync

!! !!

如果您需要身份验证,请查看ASP.NET Core Blazor authentication and authorization,因为它利用了AuthenticationStateProvider

关于检查是否已经对http客户端进行了调用,在继续之前,. . if (appState?.UserData == null) { //appData.UserData = await request user data... } // more code.. . . 应该等待await的响应。

如果httpClient有一些值,则呼叫成功。.

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...