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

Blazor-防止双重HTTP调用并等待第一个,blazor,blazor-webassembly,waithandle,Blazor,Blazor Webassembly,Waithandle,在Blazor应用程序(WebAssembly)中,我需要在ApplicationState中加载用户数据。 我的许多页面都需要此用户数据,因此在OnAfterRenderAsync方法中,如果未加载用户数据,我将加载用户数据: protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { loadingSession = true;

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

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

    }
    await base.OnAfterRenderAsync(firstRender);
}
但是如果我快速转到另一个页面,用户数据将不会被加载,页面将请求一个新的请求

因此,如果已经有请求,我想等待,而不是开始新的请求

    public async Task LoadUserData()
    {
        try
        {
            if (dataLoading)
            {
                // Need to wait the previous request
            }

            if (dataLoaded)
                return;

            dataLoading = true;
            User = await httpClient.GetFromJsonAsync<User>("users", options);
        }
        catch (Exception e)
        {
            OnException(e);
        }
        finally
        {
            if (User != null)
                dataLoaded = true;
            dataLoading = false;
        }
    }
public异步任务LoadUserData()
{
尝试
{
if(数据加载)
{
//需要等待上一个请求
}
如果(数据加载)
返回;
数据加载=真;
User=wait-httpClient.GetFromJsonAsync(“用户”,选项);
}
捕获(例外e)
{
一个例外(e);
}
最后
{
如果(用户!=null)
dataLoaded=true;
数据加载=假;
}
}
我尝试了很多事情,比如说手动重置事件,线程。在任务中睡觉,。。。但我没能正确地做到这一点。 最好的方法是什么

和OnAfterRender在组件完成渲染后调用

和OnInitialized在之后初始化组件时调用 已从中的父组件接收其初始参数 SetParametersAsync

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

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

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

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

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

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

    public UserData UserData { get; set; }

    public string SomeOtherStateValue { get; set; }
}

然后在您的
服务
中将此类注册为
Singleton
(请参阅):

这将等待对API的调用,直到它收到响应为止。 如果响应成功,即:
响应。IsSuccessStatusCode
为真。从响应消息中提取数据并将其存储在
appState.UserDate

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

在后续组件中,您可以在
OnInitializedAsync
方法中添加检查:

.
.
if (appState?.UserData == null)
{
    //appData.UserData = await request user data...
}
// more code..
.
.
!!但是,这不是应该如何处理身份验证

如果您需要身份验证,请查看它的使用情况

关于检查是否已经对http客户端进行了调用,
wait
应等待
httpClient
的响应,然后再继续


如果
appState.UserData
有一些值,则调用成功。

是的,我知道,但我有许多子组件在启动时调用相同的例程,它们需要用户数据。使用OnInitializedAsync方法,我在第一次加载时遇到了一个异常。但我的问题并不清楚,它是“如何知道HTTP请求是否已经发送,并等待它的响应来启动新请求?”那么您是否有一个充当应用程序状态的“服务”?您是否在登录后获取用户数据,然后只需要在其他组件上使用用户数据?是的,我有一个存储用户数据的应用程序状态。我也使用IdentityServer,但我不知道现在在哪里可以处理登录事件并请求用户数据。这就是我在页面中询问用户数据的原因。但是,如果我打开一个页面并立即打开第二个页面,这两个页面都将进行API调用以获取UserDataSo双重加载是否会导致问题?通常在登录后,您将通过类似于登录页面中的
Response.Redirect(*Redirect url*)
的方式重定向到索引页面。如何“快速”导航到另一个页面?通过点击链接?另一个标签和网址?在
范围之外使用导航栏?这其实不是问题,更多的是优化。例如,我通过单击导航栏快速导航。是的,在登录后,您将被重定向到您请求的页面(例如,如果您存储了指向仪表板页面的快速链接)。但您让我想到了AuthorizeView中mainLayout中的一个空组件,它是在初始化时加载数据的唯一角色。这是个好主意吗?
@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();
}

}

.
.
if (appState?.UserData == null)
{
    //appData.UserData = await request user data...
}
// more code..
.
.