Angular 2 + rxjs - 如何使用多个后续http请求返回对象的返回流

时间:2016-09-19 06:00:34

标签: angular rxjs angular2-services rxjs5

我有数据类

class Processor {
    frequency: number;
    error: booelan;
}

class Computer {
    name: string;
    processor: Processor[];
}

我使用json从后端获取它:

{
    "name": "Alfa Beta",
    "processors": [
        {
            "url": "ASD3-455R-FRTT-ASEW"
        },
        {
            "url": "AQW2-DFFFR-367K-MMKE"
        }
    ]
}

和单处理器

{
    "url": "ASD3-455R-FRTT-ASEW",
    "frequency": 2200,
    working: true
}

我需要返回Computer的流,因为我想每分钟询问处理器状态。对于单个返回的Computer实例,我需要发送3个相互依赖的http请求。当然我会为此使用服务类。对我来说唯一的麻烦就是如何创建这个流,即。 this.http.get(this.mainUrl)

我找到了Reactive programming, HTTP and Angular 2章节执行请求的结果是前一个,但它没有帮助。

1 个答案:

答案 0 :(得分:3)

这看起来像是concatMap operator的工作(顺便说一下,我前段时间有一个非常相似的问题How to use exhaustMap in ReactiveX/rxjs 5 in TypeScript)。

例如按顺序运行多个请求:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/concatMap';
import 'rxjs/add/operator/do';

var urls = [
  'https://httpbin.org/get?1',
  'https://httpbin.org/get?2',
  'https://httpbin.org/get?3',
  'https://httpbin.org/get?4',
  'https://httpbin.org/get?5',
];     

Observable.from(this.urls)
  .concatMap(url => http.get(url))
  .subscribe(response => console.log(response.url))
;

打印到控制台:

https://httpbin.org/get?1
https://httpbin.org/get?2
https://httpbin.org/get?3
https://httpbin.org/get?4
https://httpbin.org/get?5

运算符concatMap()将每个值(在我们的示例中为每个网址)映射到Observable并重新发出其所有值,直到完成为止。然后它继续从callable返回的下一个Observable。我们知道http.get()会返回Observable,只会使用Response对象发出一个值,然后完成。

请参阅plnkr演示:http://plnkr.co/edit/PJ7SpkNgBjZz2h4uvRpK?p=preview(在app.component.ts

您说请求相互依赖(一个请求取决于上一个请求的结果?)所以可能有以下更好的解决方案:

http.get('https://httpbin.org/get?1')
  .do(response => console.log('Process response', response.url))

  .concatMap(response => {
    console.log('Previous response', response.url, ' about to run /get?2')
    return http.get('https://httpbin.org/get?2')
  })
  .do(response => console.log('Process response', response.url))

  .concatMap(response => {
    console.log('Previous response', response.url, ' about to run /get?3')
    return http.get('https://httpbin.org/get?3')
  })

  .subscribe(response => console.log('Done', response.url))
;

控制台输出:

Process response https://httpbin.org/get?1
Previous response https://httpbin.org/get?1  about to run /get?2
Process response https://httpbin.org/get?2
Previous response https://httpbin.org/get?2  about to run /get?3
Done https://httpbin.org/get?3

同样,我们正在使用concatMap()将每个值转换为Observable,但这次我们只是使用它来保证正确的顺序,并且能够访问之前的结果http.get()致电。我还使用do() operator仅将处理先前响应的逻辑与创建下一个请求以获得更好可读性的逻辑分开(即使这可能全部进入concatMap())。

请参阅plnkr演示:http://plnkr.co/edit/VFv09dTekK8av1Pu3a75?p=preview(在app.component.ts