RxJS中BehaviorSubject结合switchMap刷新后无数据问题排查
问题分析与解决
代码文件
app.component.ts
import { Component, OnInit } from '@angular/core'; import { of } from 'rxjs'; import { TestService } from './test.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent implements OnInit { posts = [ { id: 1, name: 'chethan' }, { id: 2, name: 'rohan' }, { id: 3, name: 'sai' }, { id: 4, name: 'yashas' }, ]; constructor(private readonly testService: TestService) {} getPosts() { return of(this.posts); } ngOnInit(): void { this.testService.myData$.subscribe((data) => { console.log('from mydata'); console.log(data); }); // this.testService.mysecondData$.subscribe((data) => { // console.log('from secondata'); // console.log(data); // }); this.testService.refresh(); this.testService.emitProduct(3); } }
test.service.ts
import { Injectable } from '@angular/core'; import { BehaviorSubject, map, Subject, switchMap, switchMapTo, tap, } from 'rxjs'; @Injectable({ providedIn: 'root', }) export class TestService { private refreshSubject = new Subject<void>(); refresh$ = this.refreshSubject.asObservable(); private productSubject = new BehaviorSubject<number>(1); product$ = this.refreshSubject.asObservable(); mysecondData$ = this.product$.pipe( tap(() => console.log('coming to mysecondata')), map(() => 5) ); myData$ = this.refresh$.pipe( tap(() => console.log('myData before switchmap got refresh pipe')), switchMap(() => this.mysecondData$), tap(() => console.log('myData after switchmap bypassed refresh pipe')) ); emitProduct(data: number) { this.productSubject.next(data); } refresh() { this.refreshSubject.next(); } }
问题描述
调用refresh()后,预期myData$会切换到mysecondData$并输出值5,但实际未获取到product$的发射值;即使在ngOnInit中订阅testService.product$,调用productSubject.next()方法后也无法获取数据,请问原因是什么?
问题原因与修复
核心错误出在test.service.ts的product$定义上:
你把product$错误赋值为this.refreshSubject.asObservable(),但它本该和你创建的productSubject绑定。这直接导致两个关键问题:
- 调用
emitProduct()更新productSubject时,product$完全接收不到任何数据——因为它和productSubject没有任何关联; mysecondData$依赖product$,但现在product$只有在调用refresh()时才会触发,和productSubject的更新彻底脱节,自然没法得到预期输出。
修复步骤
修改test.service.ts中product$的定义,把它和productSubject绑定:
private productSubject = new BehaviorSubject<number>(1); // 替换原来的refreshSubject为productSubject product$ = this.productSubject.asObservable();
修复后,调用refresh()时,myData$会通过switchMap切换到mysecondData$,而mysecondData$依赖的product$会因为productSubject的初始值或emitProduct()的调用发射数据,最终就能输出预期的5。
内容的提问来源于stack exchange,提问作者Chethan B
相关产品推荐
相关产品推荐

