使用 AsyncEnumerable 更好的处理内容流

目录

Intro

Sample

ASP.NET Core API

HttpClient

References


Intro

.NET 8 针对 HttpClient 新增了一个 GetFromJsonAsAsyncEnumerable 的扩展,我们可以更加方便地处理内容流了

Sample

ASP.NET Core API

首先我们来定义一个 API

[Route("api/[controller]")]
public class JobsController : ControllerBase
{
    [HttpGet]
    public async IAsyncEnumerable<Jobs> Jobs()
    {
        for (var i = 0; i < 10; i++)
        {
            await Task.Delay(500);
            yield return new Jobs() { Id = i + 1, Title = $"job_{i} --- {DateTimeOffset.Now}" };
        }
    }
}

public sealed class Job
{
    public required int Id { get; set; }
    public required string Title { get; set; }
    public override string ToString() => $"JobId: {Id}, JobTitle: {Title}";
}

我们在浏览器里请求这个 API 看下响应时间,可以看到类似下面的截图,浏览器在 635.23ms 的时候就开始收到了服务器端的响应,并在后面的五秒内收到后面的内容

图片

HttpClient

接着我们来使用新的 GetFromJsonAsAsyncEnumerable 来获取数据

using var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://localhost:5297");
using var response = await httpClient.GetAsync("api/Jobs");
ArgumentNullException.ThrowIfNull(response.Content);
var stream = response.Content.ReadFromJsonAsAsyncEnumerable<Job>();
// var stream = httpClient.GetFromJsonAsAsyncEnumerable<Job>("api/Jobs");
await foreach (var job in stream)
{
    Console.WriteLine(job);
    Console.WriteLine(DateTimeOffset.Now);
}

为了方便效果对比,我们打印 response 之后打印一下时间

图片

从输出可以看到,我们在 response 刚返回还没结束就已经开始处理了,服务器端返回一条数据,客户端就输出一条数据

微软还封装了一个 GetFromJsonAsAsyncEnumerable 方法来更加便捷的使用,参考前面示例中被注释掉的代码,但是目前实现感觉有点问题,别的 json 扩展使用的是基于 web 的一个 JsonSerializerOptions 这个使用的确实 JsonSerializerOptions.Default,导致这个方法会导致序列化的时候是大小写敏感的和别的扩展方法不一致,所以上面改了一个 workaround 的写法

在 Github 上提了一个 issue https://github.com/dotnet/runtime/issues/92179 感兴趣的朋友可以看一下

References

  • https://github.com/dotnet/runtime/pull/89258

  • https://github.com/dotnet/runtime/issues/87577

  • https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/async-streams

  • https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer.deserializeasyncenumerable

  • https://github.com/dotnet/runtime/issues/92179

  • https://github.com/dotnet/runtime/pull/92180

引入地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值