ToB企服应用市场:ToB评测及商务社交产业平台

标题: .NET最佳实践:webapi返回IAsyncEnumerable提拔性能 [打印本页]

作者: 杀鸡焉用牛刀    时间: 2025-2-12 15:33
标题: .NET最佳实践:webapi返回IAsyncEnumerable提拔性能
什么是IAsyncEnumerable

IAsyncEnumerable 是 .NET 中用于表现异步数据流的接口。
它答应你逐个异步地获取数据项,而不是将所有数据一次性加载到内存中。这样可以淘汰内存占用,尤其在处理大量数据时更加高效。
与 IEnumerable 差异,IEnumerable 是同步的,要求所有数据在返回之前就加载完成。
而 IAsyncEnumerable 是异步的,支持在数据流被请求时逐步加载,适合处理从数据库或网络等源异步获取的数据。
示例:
  1. public async IAsyncEnumerable<int> GetNumbersAsync()
  2. {
  3.     for (int i = 0; i < 10; i++)
  4.     {
  5.         await Task.Delay(100);  // 模拟异步操作
  6.         yield return i;
  7.     }
  8. }
复制代码
好处

淘汰内存占用:IAsyncEnumerable 逐步加载数据,制止了必要将所有数据一次性加载到内存中。对于大数据量的查询,能显著淘汰内存压力。
提拔响应性能:在 WebAPI 中,返回 IAsyncEnumerable 可以让客户端在获取部门数据时立即开始处理,而无需等待所有数据都加载完成。这使得响应时间更短,提拔用户体验。
制止阻塞操作:使用 async/await 使得 WebAPI 不会被同步阻塞操作所拖慢,能够更好地处理并发请求。
以 WebAPI + EFCore 举例

假设我们必要通过 Entity Framework Core 从数据库中查询大量记载。
如果我们一次性加载所有数据,可能会导致内存占用过高,乃至影响性能。使用 IAsyncEnumerable,我们可以逐个获取数据。
示例代码:
  1. public class ProductController : ControllerBase
  2. {
  3.     private readonly ApplicationDbContext _context;
  4.     public ProductController(ApplicationDbContext context)
  5.     {
  6.         _context = context;
  7.     }
  8.     [HttpGet("products")]
  9.     public async IAsyncEnumerable<Product> GetProductsAsync()
  10.     {
  11.         await foreach (var product in _context.Products.AsAsyncEnumerable())
  12.         {
  13.             yield return product;
  14.         }
  15.     }
  16. }
复制代码
在这个例子中,AsAsyncEnumerable() 方法将 DbSet 转换成一个异步数据流,await foreach 循环逐个从数据库中异步获取数据并返回,制止了内存占用过多。
以 WebAPI + HTTPClient 举例

在 WebAPI 中,你可能必要调用其他服务或外部 API 来获取数据。使用 IAsyncEnumerable 可以使得调用返回的数据逐步加载,制止等待整个请求完成后再返回。
示例代码:
  1. public class ExternalApiController : ControllerBase
  2. {
  3.     private readonly HttpClient _httpClient;
  4.     public ExternalApiController(HttpClient httpClient)
  5.     {
  6.         _httpClient = httpClient;
  7.     }
  8.     [HttpGet("external-data")]
  9.     public async IAsyncEnumerable<string> GetExternalDataAsync()
  10.     {
  11.         var response = await _httpClient.GetAsync("https://api.example.com/data");
  12.         response.EnsureSuccessStatusCode();
  13.         var stream = await response.Content.ReadAsStreamAsync();
  14.         using (var reader = new StreamReader(stream))
  15.         {
  16.             string? line;
  17.             while ((line = await reader.ReadLineAsync()) != null)
  18.             {
  19.                 yield return line;
  20.             }
  21.         }
  22.     }
  23. }
复制代码
在这个例子中,我们通过 HTTPClient 请求外部 API 数据,并使用 IAsyncEnumerable 返回每一行数据,答应客户端逐步处理数据,而无需等待所有数据都加载完毕。
需使用System.Text.Json格式化程序。 使用Newtonsoft.Json或XML-based格式化程序时,会缓冲效果,造成最后一次返回。
客户端怎么处理 IAsyncEnumerable

客户端吸收到 IAsyncEnumerable 数据流后,可以使用异步迭代器 await foreach 来逐步处理数据。
这样可以在数据流逐步传输过程中实时处理和显示数据,而不必等待全部数据加载完成。
C# 客户端代码:
  1. public class ProductClient
  2. {
  3.     private readonly HttpClient _httpClient;
  4.     public ProductClient(HttpClient httpClient)
  5.     {
  6.         _httpClient = httpClient;
  7.     }
  8.     public async Task GetProductsAsync()
  9.     {
  10.          var products = _httpClient.GetFromJsonAsAsyncEnumerable("https://api.example.com/data");
  11.          await foreach (var p in products)
  12.          {
  13.             Console.WriteLine(DateTime.Now.ToString() + "  " + p.Id);
  14.          }
  15.     }
  16. }
复制代码
JavaScript 客户端处理:

在 JavaScript 中,客户端可以使用 fetch API 和流(Streams)来逐步处理数据。WebAPI 返回的数据流可以通过 Response.body.getReader() 来读取并逐步消耗。
  1. async function fetchProducts() {
  2.     const response = await fetch('https://example.com/products');
  3.     const reader = response.body.getReader();
  4.     const decoder = new TextDecoder();
  5.     let done = false;
  6.     let value = '';
  7.     while (!done) {
  8.         const { done: chunkDone, value: chunk } = await reader.read();
  9.         done = chunkDone;
  10.         value += decoder.decode(chunk, { stream: true });
  11.         console.log(value);  // 逐步输出数据
  12.     }
  13. }
复制代码
通过上述方式,JavaScript 客户端可以逐步处理 WebAPI 返回的异步流,提拔用户体验和响应速度。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4