如何将 Rx 与 C# 等待调用一起使用以从 Web 检索 JSON 数据

How can I use Rx with C# await calls to retrieve JSON data from web

我有一个方法可以使用 HttpClient 调用 API 并构建客户列表 IEnumerable<Customer>。 API 的工作方式是它一次只会 return 100 个客户,并且会在 JSON 内容中提供另一个 link 以再次获取下 100 个。

我如何构建此代码以迭代获取记录,直到获取所有记录并从此方法构建大型 IEnumerable<Customer> 和 return。我正在寻找 Rx 的解决方案。

Task<IEnumerable<Customer>> GetCustomers(string url)
{
  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.GetAsync(url);
  response.EnsureSuccessStatusCode();
  string responseBody = await response.Content.ReadAsStringAsync();
  
  // TODO: Deserialize responseBody and build a new IEnumerable<Customer>
}

Json:

{
    nextRecords: '\customers3'
    customers: [
        {
            name: 'John Doe'
        },
        {
            name: 'Mary Doe'
        }
        ]
}

我已将签名从 Task<IEnumerable<Customer>> 更改为 IObservable<Customer> 以使其更像 Rx。

您需要定义 Func<JObject, IObservable<Customer>> createCustomers 函数。

试试这个:

IObservable<Customer> GetCustomers(string url)
{
    Func<JObject, IObservable<Customer>> createCustomers = jo => { ... };
    return Observable.Create<Customer>(o =>
    {
        var final_url = url + "\customers";
        return
            Observable
                .While(
                    () => final_url != url,
                    Observable
                        .Using(
                            () => new HttpClient(),
                            client =>
                                from x in Observable.FromAsync(() => client.GetAsync(final_url))
                                from y in Observable.Start(() =>
                                {
                                    x.EnsureSuccessStatusCode();
                                    return x;
                                })
                                from z in Observable.FromAsync(() => y.Content.ReadAsStringAsync())
                                from w in Observable.Start(() =>
                                {
                                    var j = JObject.Parse(z);
                                    final_url = url + j.Property("nextRecords").Value;
                                    return createCustomers(j);
                                })
                                from v in w
                                select v))
                .Subscribe(o);
    });
}