Blazor组件中如何在foreach循环内调用返回Task的方法
Blazor foreach循环调用异步方法无法显示数据的问题
我是Blazor新手,想在组件的foreach循环里调用返回Task的方法(非点击事件触发),通过设备ID关联获取关联员工的全名。已经编写了EmployeeWithDevice方法(原本想命名为GetFullName),控制台能输出全名,但页面表格无法显示对应内容。
现有代码
Blazor组件页面代码
<table class="table custom-table"> <thead> <tr> <th>Full Name</th> </tr> </thead> <tbody> @foreach (var device in DeviceService.device){ GetFullName(device.Id) ; // 这里有问题? @FullName // 期望显示John Smith } </tbody> </table>
代码逻辑部分
@code{ private string FullName = string.Empty; private async Task<string> EmployeeWithDevice(int deviceId) { // 通过deviceId从数据库获取设备借还记录 var result = await DeviceLoanService.GetDeviceLoanById(deviceId); var Loan = result.Data; if (result.Success) { FullName = $"{Loan?.Employee?.Person?.FirstName}, {Loan?.Employee?.Person?.LastName}"; } // Console.WriteLine(FullName); 控制台能输出正确全名 return FullName; } }
问题原因
- 直接在foreach循环中调用异步方法
EmployeeWithDevice但未等待,异步操作还未完成就渲染@FullName,此时变量还是初始空值。 - 共享的
FullName变量会被所有循环项覆盖,就算等待异步完成,最终也只会显示最后一个设备对应的员工名。
解决方法
方法一:提前批量加载数据(推荐)
在组件初始化时一次性获取所有设备对应的员工全名,避免循环中多次发起异步请求:
@code{ // 存储设备与对应员工全名的集合 private List<(Device Device, string FullName)> DeviceWithFullNames = new(); protected override async Task OnInitializedAsync() { foreach (var device in DeviceService.device) { var fullName = await EmployeeWithDevice(device.Id); DeviceWithFullNames.Add((device, fullName)); } } private async Task<string> EmployeeWithDevice(int deviceId) { var result = await DeviceLoanService.GetDeviceLoanById(deviceId); if (result.Success && result.Data?.Employee?.Person != null) { return $"{result.Data.Employee.Person.FirstName}, {result.Data.Employee.Person.LastName}"; } return string.Empty; } }
修改表格循环逻辑:
<table class="table custom-table"> <thead> <tr> <th>Full Name</th> </tr> </thead> <tbody> @foreach (var item in DeviceWithFullNames){ <tr> <td>@item.FullName</td> </tr> } </tbody> </table>
方法二:使用异步子组件
如果必须在循环中单独加载每个项的数据,可以创建子组件来处理异步逻辑:
创建DeviceEmployeeName.razor子组件:
@code{ [Parameter] public int DeviceId { get; set; } private string FullName { get; set; } = string.Empty; protected override async Task OnInitializedAsync() { FullName = await EmployeeWithDevice(DeviceId); } private async Task<string> EmployeeWithDevice(int deviceId) { var result = await DeviceLoanService.GetDeviceLoanById(deviceId); if (result.Success && result.Data?.Employee?.Person != null) { return $"{result.Data.Employee.Person.FirstName}, {result.Data.Employee.Person.LastName}"; } return string.Empty; } }
父组件中使用子组件:
<table class="table custom-table"> <thead> <tr> <th>Full Name</th> </tr> </thead> <tbody> @foreach (var device in DeviceService.device){ <tr> <td><DeviceEmployeeName DeviceId="@device.Id" /></td> </tr> } </tbody> </table>
关键注意事项
- 不要在同步渲染的foreach循环中直接调用异步方法,必须等待异步操作完成后再渲染数据。
- 避免用单个共享变量存储多个循环项的结果,每个项应拥有独立的数据存储。
- 批量加载数据能减少数据库请求次数,提升组件性能。
内容的提问来源于stack exchange,提问作者LINDOKUHLE MAGAGULA
相关产品推荐
相关产品推荐

