问题描述
在我的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
有一些值,则呼叫成功。.