Angular 5中Subject.next(value)不触发问题求助
解决Subject订阅后收不到值的问题
我来帮你排查这个问题!你遇到的核心问题是Subject的特性导致的——Subject是一种热Observable,但它不会保存任何历史发射的值。如果你的组件在pdfLink.next(pdf.url)执行之后才完成订阅,那组件就接收不到这个已经发射过的值了。
举个场景:假设你先调用了getPdfById,HTTP请求很快完成并发射了pdf.url,之后某个组件才初始化并执行ngOnInit里的订阅,这时候Subject不会把之前发射的值推送给新的订阅者,所以你的日志自然没输出。
解决方案:换成BehaviorSubject或ReplaySubject
这两种Observable类型会保存历史值,能完美解决你当前的问题:
方案1:使用BehaviorSubject
BehaviorSubject会保存最后一次发射的值,新订阅的观察者会立即收到这个最新值(需要给它一个初始值,比如空字符串或null):
import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class SomeService { private pdfLink = new BehaviorSubject<string>(''); // 设置初始值 pdfLinkCast = this.pdfLink.asObservable(); getPdfById(id: string): void { this.httpClient.get<any>(this.apiUrl + id + '/pdf', this.httpOptions).subscribe((pdf) => { console.log(pdf); this.pdfLink.next(pdf.url); }); } }
方案2:使用ReplaySubject
ReplaySubject可以保存指定数量的历史值(比如保存最近1个),不需要初始值:
import { ReplaySubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class SomeService { private pdfLink = new ReplaySubject<string>(1); // 保存最近1次发射的值 pdfLinkCast = this.pdfLink.asObservable(); getPdfById(id: string): void { this.httpClient.get<any>(this.apiUrl + id + '/pdf', this.httpOptions).subscribe((pdf) => { console.log(pdf); this.pdfLink.next(pdf.url); }); } }
额外检查点
还要确保你的服务是单例实例:比如服务的@Injectable装饰器里设置了providedIn: 'root',或者在根模块的providers数组里声明了它。如果组件和服务用的不是同一个实例,订阅也会失效。
另外,记得在组件的ngOnDestroy钩子中取消订阅,避免内存泄漏:
ngOnDestroy() { this.subscription.unsubscribe(); }
内容的提问来源于stack exchange,提问作者Shaun Chua
相关产品推荐
相关产品推荐

