Javascript 使用rxjs ReplaySubject在两个组件之间共享数据的正确方式是什么?

Javascript 使用rxjs ReplaySubject在两个组件之间共享数据的正确方式是什么?,javascript,angular,rxjs,angular-services,angular-components,Javascript,Angular,Rxjs,Angular Services,Angular Components,我开发了一个包含两个视图的组件。组件A有一个联系表单,组件B是“谢谢”页面 A部分: 你填写表格并提交。 一旦响应到达,就会创建一个新的ReplaySubject值。 用户将被路由到组件B B部分: 组件已初始化。 组件从主题获取值。 将呈现视图并显示感谢消息 HTTP调用响应(表单数据发布请求成功后返回): 组件A(表格)代码: 组件B(谢谢页面)代码: 组件B模板(谢谢页面): {{msg.message} 组件服务代码: import { Injectable } from '@ang

我开发了一个包含两个视图的组件。组件A有一个联系表单,组件B是“谢谢”页面

A部分: 你填写表格并提交。 一旦响应到达,就会创建一个新的ReplaySubject值。 用户将被路由到组件B

B部分: 组件已初始化。 组件从主题获取值。 将呈现视图并显示感谢消息

HTTP调用响应(表单数据发布请求成功后返回):

组件A(表格)代码:

组件B(谢谢页面)代码:

组件B模板(谢谢页面):


{{msg.message}
组件服务代码:

import { Injectable } from '@angular/core';
import { HttpResponse } from '@angular/common/http';

import { Observable, ReplaySubject } from 'rxjs';
import { map, take } from 'rxjs/operators';

import {
  RequestCardDataService,
  Item,
  ItemCreated
} from '@example/request-card-data';

@Injectable()
export class RequestCardWidgetService {

  constructor(private dataService: RequestCardDataService) { }

  private readonly results = new ReplaySubject<ItemCreated>();

  readonly message: Observable<ItemCreated> = this.results; // Message Line. This is the variable that I'm rendering in the template. Is this the correct way of extracting subject values?

  requestCard (card: Item): Observable<ItemCreated> {
    return this.dataService.postCardRecord(card).pipe(
      take(1),
      map((response: HttpResponse<ItemCreated>): ItemCreated | {} => {
        return response.body
          ? response.body
          : {};
      })
    );
  }

  processResult(data: ItemCreated) {
    this.results.next(data);
  }

}
从'@angular/core'导入{Injectable};
从'@angular/common/http'导入{HttpResponse};
从“rxjs”导入{Observable,ReplaySubject};
从'rxjs/operators'导入{map,take};
进口{
RequestCardDataService,
项目,,
项目创建
}来自“@示例/请求卡数据”;
@可注射()
导出类RequestCardWidgetService{
构造函数(私有数据服务:RequestCardDataService){}
私有只读结果=新的ReplaySubject();
只读消息:Observable=this.results;//消息行。这是我在模板中呈现的变量。这是提取主题值的正确方法吗?
请求卡(卡:项目):可观察{
返回此.dataService.record(card).pipe(
以(1)为例,
map((响应:HttpResponse):itemscreated |{}=>{
返回响应.body
?响应。主体
: {};
})
);
}
processResult(数据:ItemCreated){
这个。结果。下一个(数据);
}
}
概述: 组件A有一个表单。提交表单后,结果将作为新值存储在subject中。用户将被路由到“谢谢”页面。 感谢页面组件呈现元素并从主题获取最新值。然后呈现内容

这段代码有效,但我确实有一些问题

问题: 这是使用该主题的正确方式吗

这是:

readonly message: Observable<ItemCreated> = this.results;
readonly message:Observable=this.results;
从主题中提取价值的正确方法是什么?(我正在向视图传递“消息”。)

有没有更好的方法达到同样的效果? 非常感谢。

这是使用主题的正确方式吗?
ReplaySubect
unconstraint将重播它以前发送给新订阅者的所有值。这可能导致用户在最终接收到当前消息之前可以接收以前发出的消息的情况。因此,要么约束主题,要么考虑使用<代码>行为主题< /代码>。p> 从主题中提取价值 一个
主体
及其所有衍生物都是
可观察的
s和
观察者
s。向消费者提供主题时,您不希望公开
观察者
界面,即消费者永远不能调用
下一步
错误
完成
。因此,正如评论中所建议的那样,您应该首先调用
asObservable
方法,确保只向消费者公开
Observable
接口

readonly message:Observable=this.results.asObservable()

下一步 如果您想继续在组件之间使用基于服务的通信,那么我认为您有机会根据问题注释中链接的文档清理/完善代码

如果您的应用程序变得越来越复杂,我将引导您采用Redux风格的体系结构,并特别研究如何使用效果来管理副作用

通过简单、谨慎的可观察结构,特效可以满足您的所有需求,即处理表单提交、接收响应甚至导航到成功页面的特效

对于简单的任务来说,redux体系结构可能有些过分,但是如果您正在处理管理大型状态树的大型应用程序,我更喜欢这种方法,而不是基于服务的集成。

这是使用主题的正确方法吗?
ReplaySubect
unconstraint将重播它以前发送给新订阅者的所有值。这可能导致用户在最终接收到当前消息之前可以接收以前发出的消息的情况。因此,要么约束主题,要么考虑使用<代码>行为主题< /代码>。p> 从主题中提取价值 一个
主体
及其所有衍生物都是
可观察的
s和
观察者
s。向消费者提供主题时,您不希望公开
观察者
界面,即消费者永远不能调用
下一步
错误
完成
。因此,正如评论中所建议的那样,您应该首先调用
asObservable
方法,确保只向消费者公开
Observable
接口

readonly message:Observable=this.results.asObservable()

下一步 如果您想继续在组件之间使用基于服务的通信,那么我认为您有机会根据问题注释中链接的文档清理/完善代码

如果您的应用程序变得越来越复杂,我将引导您采用Redux风格的体系结构,并特别研究如何使用效果来管理副作用

通过简单、谨慎的可观察结构,特效可以满足您的所有需求,即处理表单提交、接收响应甚至导航到成功页面的特效

对于简单的任务来说,redux体系结构可能有些过分,但如果您正在处理一个管理大型状态树的大型应用程序,我更喜欢这种方法,而不是基于服务的I
import { Component } from '@angular/core';
import { RequestCardWidgetService } from './request-card-widget.service';

@Component({
  selector: 'pt-request-card-success',
  templateUrl: './request-card-success.template.html'
})
export class RequestCardSuccessComponent {
  messages: any; // TODO: To use the proper type...

  constructor( private requestCardService: RequestCardWidgetService) {
    this.messages = this.requestCardService.message;
  }
}
<div *ngIf='(messages | async) as msg'>
  {{ msg.message}}
</div>
import { Injectable } from '@angular/core';
import { HttpResponse } from '@angular/common/http';

import { Observable, ReplaySubject } from 'rxjs';
import { map, take } from 'rxjs/operators';

import {
  RequestCardDataService,
  Item,
  ItemCreated
} from '@example/request-card-data';

@Injectable()
export class RequestCardWidgetService {

  constructor(private dataService: RequestCardDataService) { }

  private readonly results = new ReplaySubject<ItemCreated>();

  readonly message: Observable<ItemCreated> = this.results; // Message Line. This is the variable that I'm rendering in the template. Is this the correct way of extracting subject values?

  requestCard (card: Item): Observable<ItemCreated> {
    return this.dataService.postCardRecord(card).pipe(
      take(1),
      map((response: HttpResponse<ItemCreated>): ItemCreated | {} => {
        return response.body
          ? response.body
          : {};
      })
    );
  }

  processResult(data: ItemCreated) {
    this.results.next(data);
  }

}
readonly message: Observable<ItemCreated> = this.results;