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

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;
    }
}

问题原因

  1. 直接在foreach循环中调用异步方法EmployeeWithDevice但未等待,异步操作还未完成就渲染@FullName,此时变量还是初始空值。
  2. 共享的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:01:37