使用 RxJs 级联 ajax 调用 [英] Cascading ajax calls with RxJs

查看:64
本文介绍了使用 RxJs 级联 ajax 调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何级联 RxJs 调用以从这个人为的服务中检索数据.

第一个请求去/customer/1

/customer/:id

回复:

<代码>{姓名:汤姆",发票:[1,3],订单:[5,6]}

在客户响应中,我们使用 2 个 InvoiceId 来访问第二个服务:

/invoices/:id

回复

<代码>{编号:1,数量:10}

在客户响应中,我们使用 2 个 OrderId 来访问第三个服务:

/orders/:id

回复

<代码>{编号:2,日期:'2016-11-12'}

最后我想得到一个看起来像这样的对象:

<代码>{姓名:汤姆",发票: [{编号:1,数量:10},{编号:3,数量:5}],命令: [{编号:5,日期:'2016-11-12'},{编号:6,日期:'2016-11-12'}]}

如何通过管道传递 id 以便检索依赖对象.

我的直觉告诉我,我可能应该使用 flatMap 运算符,但我完全不确定这一切如何协同工作.

var ajax = Rx.DOM.getJSON('/api/customers/1').flatMap(p => p.Invoices.map(x =>Rx.DOM.getJSON('/api/invoices/' + x)));

解决方案

这是一个典型的用例,您需要从多个 HTTP 调用中构建响应:

const Observable = Rx.Observable;var customerObs = Observable.create(observer => {Observable.of({Name: "Tom", Invoices: [1,3], Orders: [5,6]}).订阅(响应=> {变量结果 = {名称:响应.名称,发票:[],命令: [],};让发票Obs = Observable.from(response.Invoices).flatMap(id => Observable.of({ Id: Math.round(Math.random() * 50), Amount: Math.round(Math.random() * 500) }).delay(500)).toArray();让 ordersObs = Observable.from(response.Orders).flatMap(id => Observable.of({ Id: Math.round(Math.random() * 50), Amount: Math.round(Math.random() * 500) }).delay(400)).toArray();Observable.forkJoin(invoicesObs, ordersObs).subscribe(responses => {result.Invoices = 响应[0];结果.订单=响应[1];观察者.下一个(结果);});});});customerObs.subscribe(customer => console.log(customer));

观看现场演示:https://jsfiddle.net/martinsikora/uc1246cx/>

我使用 Observable.of() 来模拟 HTTP 请求,flatMap() 将每个发票/订单 ID 转换为 Observable(另一个 HTTP 请求)重新发送,然后 toArray() 收集从操作符链发出的所有值并将它们重新发送到单个数组中(只是因为它很方便).

Operator forkJoin() 等待所有源 Observables 完成,然后将它们的最后一个值作为数组发出(因此我们在 responses 中拥有数组数组).

看到一个类似的问题:在 rxjs 中执行高级 http 请求

How can I cascade RxJs calls to retrieve data from this contrived service.

First request goes to /customer/1

/customer/:id

Response:

{
   Name: "Tom",
   Invoices: [1,3],
   Orders: [5,6]
}

In the customer response there are 2 InvoiceIds that we use to access second service:

/invoices/:id

Response

{
  Id: 1,
  Amount: 10
}

In the customer response there are 2 OrderIds that we use to access third service:

/orders/:id

Response

{
  Id:2,
  Date: '2016-11-12'        
}

At the end I would like to kome up with an object looking like this:

{
   Name: "Tom",
   Invoices: [
    {
      Id: 1,
      Amount: 10
    },
    {
      Id: 3,
      Amount: 5
    }],
   Orders: [
   {
     Id:5,
     Date: '2016-11-12'        
   },
   {
     Id:6,
     Date: '2016-11-12'        
   }]
}

How can I pass the ids through the pipeline so that the dependant objects are retrieved.

My gut feeling tells me I should probably use the flatMap operator, but I am totally uncertain how this could all work together.

var ajax = Rx.DOM.getJSON('/api/customers/1')
    .flatMap(p => p.Invoices.map(x =>
        Rx.DOM.getJSON('/api/invoices/' + x)
        ));

解决方案

This is a typical use-case where you need to construct a response out of several HTTP calls:

const Observable = Rx.Observable;

var customerObs = Observable.create(observer => {
    Observable.of({Name: "Tom", Invoices: [1,3], Orders: [5,6]})
        .subscribe(response => {
            var result  = {
                Name: response.Name,
                Invoices: [],
                Orders: [],
            };

            let invoicesObs = Observable.from(response.Invoices)
                .flatMap(id => Observable.of({ Id: Math.round(Math.random() * 50), Amount: Math.round(Math.random() * 500) }).delay(500))
                .toArray();

            let ordersObs = Observable.from(response.Orders)
                .flatMap(id => Observable.of({ Id: Math.round(Math.random() * 50), Amount: Math.round(Math.random() * 500) }).delay(400))
                .toArray();

            Observable.forkJoin(invoicesObs, ordersObs).subscribe(responses => {
                result.Invoices = responses[0];
                result.Orders = responses[1];

                observer.next(result);
            });

        });
});

customerObs.subscribe(customer => console.log(customer));

See live demo: https://jsfiddle.net/martinsikora/uc1246cx/

I'm using Observable.of() to simulate HTTP requests, flatMap() to turn each invoice/order id into an Observable (another HTTP request) that are reemitted and then toArray() to collect all values emitted from an operator chain and reemit them in a single array (just because it's convenient).

Operator forkJoin() waits until all source Observables complete and then emits their last value as an array (so we haw array of arrays in responses).

See a similar question: Performing advanced http requests in rxjs

这篇关于使用 RxJs 级联 ajax 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆