Angular 2 + rxjs - 如何返回通过多个后续 http 请求获取的对象流

标签 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 和章节使用前一个请求的结果执行请求,但没有帮助。

最佳答案

这看起来像是 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

Operator concatMap() 将每个值(在我们的例子中为每个 URL)映射到一个 Observable 并重新发出其所有值,直到完成。然后它继续处理从可调用对象返回的下一个 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中)

关于Angular 2 + rxjs - 如何返回通过多个后续 http 请求获取的对象流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39566268/

相关文章:

angular - 如何动态设置组件宿主样式Angular 8

javascript - Angular 2,Auth0 未捕获语法错误 : Unexpected token <

javascript - Observable - 满足条件时停止序列

javascript - "current value"独立于订阅者的概念

typescript - 具有基本安全授权的 Angular 2 调用 API

javascript - 如何处理 typescript 中异步函数的返回值?

angular - 如何检查哪个组件/服务正在以 Angular 2,4 调用服务中的方法?

angular - 通过查询组件的模板获取 FormControl 实例

javascript - 如何使用 tensorflow.js 以 Angular 正确上传预训练模型?

angular - RxJs subject.subscribe 方法未按预期工作