【问题标题】:Share data api with BehaviorSubject - architecture Observables Store与 BehaviorSubject 共享数据 api - 架构 Observables Store
【发布时间】:2021-10-06 14:40:25
【问题描述】:

我只想在 api 中进行调用并在可观察对象中重用数据,就像 redux 中的一种存储。

API 网址: http://demo5095413.mockable.io/consolidado

Stackblitz 项目 https://stackblitz.com/edit/angular-ivy-iy9zhv?file=src/app/core.service.ts

负责与api连接的服务

@Injectable({
  providedIn: 'root'
})
export class ConsolidadoApi {
  
  constructor(private http: HttpClient) { }

  getInvestiments(): Observable<any> {
    return this.http.get<PosicaoConsolidada>(`${environment.basePosicaoConsolidada}`)
      .pipe(
        map(res => res),
        shareReplay(),
      )
  }
}

处理数据的服务,我的门面层(store) 最初通过这种方式,这个 observable 负责在 api 中进行调用。最后我发出一个 BehaviorSubject

export class CoreService {

    private subject = new BehaviorSubject<any>([]);
    investment$: Observable<any> = this.subject.asObservable();
    
    constructor(private api: ConsolidadoApi, private loadingService: LoadingService, public messagesService: MessagesService, public state: StateService) {
        this.getInvesmentsPortifolio$()
     }

    public getInvesmentsPortifolio$(): Observable<Carteiras> {
        return this.api.getInvestiments()
            .pipe(
                map(response => response.carteiras),
                catchError(err => {
                    const message = "Error Investments";
                    this.messagesService.showErrors(message);
                    console.log(message,err);
                    return throwError(err);
                }),
                tap(investment$ => this.subject.next(investment$))
            )
    }

这就是我想做的,访问已经拥有所有投资组合的 observable,然后从投资组合“Agora”中创建一个 observable

getPortifolioAgora(): Observable<any> {
    return this.investment$
        .pipe(
            map(response => response.carteiras.find(
                carteira => carteira.tipoInvestimento === "AGORA"
            ))
        );
}

但在我的组件中不起作用

    constructor(public coreService: CoreService, private loadingService: LoadingService) { }

  ngOnInit(): void {
    this.loadData()
  }

  public loadData(){
    this.loadingService.loadingOn()
    
    this.coreService.getPortifolioAgora().subscribe(res => {
      console.log(res)
    })

    this.coreService.getInvesmentsPortifolio$().subscribe(res => {
      this.carteiras = res
      console.log('All portifolio investments----->',res)
    })

  }

属性未定义?

我知道如果我这样做的话,find 的工作原理。

// In this observable I access directly in the api and I can access the investment portfolio Agora
// it's working, but I wouldn't want to do it that way because I would have made another call on the server
public portifolioAgora$(): Observable<Carteiras> {
    return this.api.getInvestiments()
        .pipe(
            map(response => response.carteiras.find(
                carteira => carteira.tipoInvestimento === "AGORA"
            )),
            finalize(() => this.loadingService.loadingOff())
            //tap(data => console.log(data, JSON.stringify(data)))
        )
}

【问题讨论】:

    标签: angular typescript rxjs


    【解决方案1】:

    由于在getInvesmentsPortifolio$() 中,您仅将carteiras 数组添加到BehaviourSubject 中,因此,在getPortifolioAgora 中将映射代码更新为

     getPortifolioAgora(): Observable<any> {
        return this.investment$.pipe(
          map((response) =>
            response.find((carteira) => carteira.tipoInvestimento === 'AGORA')
          )
        );
      }
    

    问题也可能是您在getInvesmentsPortifolio$ 之前调用getPortifolioAgora,在初始加载时Subject 中将无法获得结果

    【讨论】:

    • 我不明白。我将在哪里进行此更改,据我了解,您要求我更改我不想使用的功能,即有效的功能。我想在组件中重用 getPortifolioAgora() 而不是 portifolioAgora$()。我在stackblitz.com/edit/angular-ivy-iy9zhv?file=src/app/… 创建项目,请问你可以通过stackblitz 给我看吗?
    • 是的,我说的是getPortifolioAgora方法
    • 查看getInvesmentsPortifolio$()内部,您将响应映射到response.carteiras,所以现在在map管道之后的每个管道都会收到carteiras数组,而不是response.carteiras,还有这个-> @然后 987654337@ 将在 BehavoiurSubject 中添加 carteiras 数组而不是整个响应对象。但是,如果您看到 getPortifolioAgora 方法,您正在使用 response.carteiras 来查找结果,但它应该只是 carteiras 因为您在 Subject 中有数组而不是响应对象。希望你明白我的意思
    • stackblitz.com/edit/… 此处我无法从端点获取数据,因此find 将返回未定义,但您可以在此处查看代码。
    • @GuilhermeLucas 实际上我们需要在 CoreService 中订阅,否则它永远不会触发。 constructor(private api: ConsolidadoApi) { this.getInvesmentsPortifolio$().subscribe(); }
    【解决方案2】:

    @navnath 回答了我的问题,放在这里说清楚

    investments$ 在 getPortifolioAgora() 中未定义,因为 getInvesmentsPortifolio$() 未在构造函数中订阅。

    构造函数必须保持这种状态:

    constructor(private api: ConsolidadoApi, private loadingService: LoadingService, public messagesService: MessagesService, public state: StateService) {
        this.getInvesmentsPortifolio$().subscribe()
     }
    

     getPortifolioAgora(): Observable<any> {
        return this.investment$.pipe(
          map((response) =>
            response.find((carteira) => carteira.tipoInvestimento === 'AGORA')
          )
        );
      }
    

    【讨论】:

      猜你喜欢
      • 2012-08-27
      • 2021-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-10
      • 1970-01-01
      • 2020-01-29
      相关资源
      最近更新 更多