当前位置: 首页 > 知识库问答 >
问题:

角度/RxJS多播可观测的

郑高驰
2023-03-14

我有一个HTTP请求,希望将结果共享给多个组件。当然,HTTP请求返回一个可观察的。我希望多个组件能够订阅此服务,而不会触发额外的HTTP请求

我在一个组件中使用Subject实现了这一点,该组件按需发出HTTP请求,并有另一种方法订阅该主题。虽然这是可行的,但似乎有些过分,而且肯定有更好的方法。

主题服务

@Injectable()
export class EventService {
    subject: BehaviorSubject<any> = new BehaviorSubject<any>(Observable.create());

    constructor(private api: Api) {}

    fetch = () => {
        this.subject.next(
            this.api.getUsers().pipe(share())
        );
    };

    listen = (): Observable<any> => {
        return this.subject.asObservable();
    };
}

和一个订户

@Injectable
export class EventListenerA {
    constructor(private eventService: EventService){
        eventService.fetch(); // make initial call
        eventService.listen().subscribe(o => {
             o.subscribe(httpResponse => {
                 //do something with response
             })
        });
    }
}

和第二个订户

@Injectable
export class EventListenerB {
    constructor(private eventService: EventService){
        eventService.listen().subscribe(o => {
             o.subscribe(httpResponse => {
                 //do something else with response
             })
        });
    }
}

从管道链中删除share()时,会发出多个网络请求。是否有一种更优雅/正确的方式将观察到的信息传递给主题的下一个?或者完全是另一种模式


共有1个答案

严修德
2023-03-14

您应该使用ReplaySubject(),而不给它一个初始值。这样,当组件订阅listen()时,它将等待数据可用。

不需要与其他组件共享HTTP observable。只需订阅HTTP请求,然后将值发送到ReplaySubject()。任何侦听的组件都将接收数据。

@Injectable()
export class EventService {
     private _events: ReplaySubject<any> = new ReplaySubject(1);

     public constructor(private _api: ApiService) {}

     public fetch() {
         this.api.getUsers().subscribe(value => this._events.next(value));
     }

     public listen() {
         return this._events.asObservable();
     }
 }

 @Injectable
 export class EventListenerA {
     constructor(private eventService: EventService){
          eventService.fetch();
          eventService.listen().subscribe(o => {
              // prints user data
              console.log(o); 
          });
     }
}

每次有人调用eventService.fetch()它都会触发HTTP请求。如果您希望执行此请求一次,那么可以从服务构造函数或应用程序中仅发生一次的另一个点(即模块构造函数)调用fetch()

 类似资料:
  • 我有一个服务,有一个方法foo。在该方法中,我订阅了一个可观察的(超文本传输协议-客户端)。 我喜欢从foo返回一个布尔值,该值取决于get。这不起作用,因为http.get是asynchrouns-在http.get完成之前调用return。 我怎样才能使这个同步? 编辑 返回可观察的布尔值在这里不是一个选项。这是因为我处理get in foo的响应(此处未显示),但我也需要根据它的返回来执行f

  • 我有一个沙盒,它订阅了一个消息流,我想过滤该流,以查找已发送到或从特定用户使用另一个组件中指定的路由参数接收的消息。 messages.sandbox.ts: messages.detail.container.ts this.matching消息$似乎只包括this.received消息$但是我知道this.sent消息$不是空,因为我可以在我的模板中使用它没有问题。 我是不是遗漏了一些合并观测

  • 我正在努力理解rxJs观察者/可观察的。 我有一个Angular应用程序,其中一个服务创建一个可观察的: 闲聊服务ts: 当聊天室中收到消息时。服务ts,消息(假定)是多播的: 两个组件以这种方式订阅可观察对象: 问题:只有一个(最后一个订阅的)收到消息。 问:我如何配置可观察到多播到所有订阅者?

  • 我试图创建一个可观察变量,当localStorage变量发生更改时返回值。我的订户在更改localStorage(或内存中的变量)时没有获得新值。 流动看起来像 步骤 1 - 导航栏订阅用户服务(获取默认值 loggedIn=false) 步骤 2 - 身份验证组件更新用户服务(设置 loggedIn = true) 我在导航栏中的订阅未更新。我在这里错过了什么。我是否需要像事件发射器一样在Use

  • 以下代码未订阅: 但是如果我这样做,它确实订阅: 更新:这个工作太 但当我添加逻辑时,它并没有 我遵循RxJS官方文档:https://rxjs-dev.firebaseapp.com/api/operators/find 我甚至必须在,当我执行时,什么也不会打印出来。我也尝试过使用管道。 对象: 我传递的昵称是将对象与“Devpato”进行比较

  • 学习角得到服务和组件和可观察性。 我正在尝试在我的演示应用程序中实现暗模式。该控件由一个服务完成,该服务根据浏览器默认值(如果找到)设置暗主题。 它在应用程序组件中初始化,以便以后在应用程序中放置控制开关。 暗模式从布尔值开始工作,因此为true或false。据我所知,使用一个可观察对象是不够的,因为我希望多个订阅者都以两种方式绑定到订阅,每种方式在服务中切换这些可观察对象。到目前为止,我很肯定这