如何创建一个发出动态请求的 http observable [英] How to create an http observable that makes dynamic requests

查看:15
本文介绍了如何创建一个发出动态请求的 http observable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个发出动态请求的 observable.

例如

getFlowers(params?: any): Observable{返回 this.http.get(`http://flowers.com/flowers`,{ 参数})}

现在,上面的函数返回新的 http 可观察到的每个函数调用.我想以某种方式实现返回相同的可观察实例(尽管进行了不同的 http 调用),以便我可以使用 switchMap 取消之前的同时请求.

我有一个想法,我应该创建一个 Observable 属性(单例),但我没有意识到如何使用它.

解决方案

现在,上面的函数在每次函数调用时都会返回新的 http observable??

这实际上是 HTTP observables 的正常行为,因为它们是 Cold 的.当一个冷的 observable 有多个 subscribers 时,整个数据流会为每个 subscriber 重新发送.每个订阅者都变得独立并获得自己的数据流
方法:1
为避免重复 HTTP 请求,您可以使用 shareReplay 运算符.

import { HttpClient } from "@angular/common/http";import { Observable } from "rxjs";import { shareReplay, tap } from "rxjs/operators";@Injectable()导出类 ShareService {公开回应$: Observable;构造函数(私有 httpc:HttpClient){this.sendRequest();}公共发送请求(){this.response$ = this.httpc.get("url").pipe(抽头(res => {console.log("调用");返回资源;}),分享重播(1));}取数据(){返回 this.response$;}}

组件 1:

constructor(service: ShareService) {service.fetchData().subscribe(result => {控制台日志(结果);});}

组件 2:

 构造函数(服务:ShareService){service.fetchData().subscribe(result => {控制台日志(结果);});}

进一步阅读

现场演示
方法:2
如果您的目标是多播数据,请使用 RXJS 的 SubjectBehaviorSubject
Subject 充当源 Observable 和许多 observers 之间的桥梁/代理,使多个 observers 成为可能共享相同的 Observable 执行.
这种暴露主题的推荐方法是使用 asObservable() 运算符.

@Injectable()导出类 MyProvider {private myObservable=new Subject();CurrentData = this.myObservable.asObservable();构造函数(私有 aFs:AngularFirestore){//你的逻辑this.myObservable.next(value);//将数据推入observable}}

Page.ts

this.mySubscription = this.myProvider.CurrentData.subscribe(value => {//有用的东西});

使用行为主体

@Injectable()导出类 MyProvider {private myObservable = new BehaviorSubject("");CurrentData = this.myObservable.asObservable();构造函数(私有 aFs:AngularFirestore){}获取数据(我的参数):无效{一些异步调用.管道(地图(),筛选()).subscribe(value => this.myObservable.next(value));}}

Page.ts

this.myProvider.getData(param);this.mySubscription = this.myProvider.CurrentData.subscribe(value => {//有用的东西});

主题与行为主题

LiveDemo

I have an observable that makes dynamic requests.

For example,

getFlowers(params?: any): Obeservable<Flower[]> {
  return this.http.get<Flower[]>(
    `http://flowers.com/flowers`, { params }
  )
}

Now, the above function returns new http observable each function call. I would like to somehow achieve returning the same observable instance (despite making different http calls) such that I can use switchMap to cancel previous simultaneous requests.

I have an idea that I should create an Observable property (singleton), but I fail to realize how to utilize it.

解决方案

Now, the above function returns new http observable each function call??

This is actually the normal behavior of the HTTP observables as they are Cold. When a cold observable has multiple subscribers, the whole data stream is re-emitted for each subscriber. Each subscriber becomes independent and gets its own stream of data
Approach:1
To Avoid Duplication of HTTP Requests you can use shareReplay operator.

import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { shareReplay, tap } from "rxjs/operators";
@Injectable()
export class ShareService {
  public response$: Observable<any>;
  constructor(private httpc: HttpClient) {
    this.sendRequest();
  }
  public sendRequest() {
    this.response$ = this.httpc.get("url").pipe(
      tap(res => {
        console.log("called");
        return res;
      }),
      shareReplay(1)
    );
  }
  fetchData() {
    return this.response$;
  }
}

component1:

constructor(service: ShareService) {
    service.fetchData().subscribe(result => {
      console.log(result);
    });
  }

component2:

   constructor(service: ShareService) {
    service.fetchData().subscribe(result => {
      console.log(result);
    });
  }

Further Reading

Live Demo
Approach:2
If your objective is to multicast the data use RXJS's Subject or BehaviorSubject
Subject acts as a bridge/proxy between the source Observable and many observers, making it possible for multiple observers to share the same Observable execution.
This recommended way of exposing Subjects are using the asObservable() operator.

@Injectable()
export class MyProvider {
  private myObservable=new Subject<any>();
  CurrentData = this.myObservable.asObservable();
  constructor(private aFs: AngularFirestore) {
    //your logic
      this.myObservable.next(value);//push data into observable
  }


}

Page.ts

this.mySubscription = this.myProvider.CurrentData.subscribe(value => {
      //something that works
    });

Using Behavior Subject

@Injectable()
export class MyProvider {
  private myObservable = new BehaviorSubject<any>("");
  CurrentData = this.myObservable.asObservable();
  constructor(private aFs: AngularFirestore) {}

  getData(myParam): void {
    someasynccall
      .pipe(
        map(),
        filter()
      )
      .subscribe(value => this.myObservable.next(value));
  }
}

Page.ts

this.myProvider.getData(param);
this.mySubscription = this.myProvider.CurrentData.subscribe(value => {
      //something that works
    });

Subject vs BehaviorSubject

LiveDemo

这篇关于如何创建一个发出动态请求的 http observable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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