Angular 2 Subject无观察者问题:takeUntil unsubscribe实现疑惑
为什么takeUntil的Subject在ngOnDestroy中observers数组长度为0?
这其实是完全合理的现象,不用过度担忧!我们来一步步拆解原因:
1. 单次Observable的自动退订逻辑
你代码里的carsService.getDetails(this.id)大概率是一个HTTP请求(Angular HttpClient的请求默认是单次发射数据后就自动完成的Observable)。当这个Observable发射完数据(拿到car对象)或者抛出错误时,它会自动调用订阅的complete或error方法,此时订阅会被自动取消,对应的Subject的observers数组就会被清空。
这种情况下,takeUntil(this.ngUnsubscibe)其实并没有真正触发退订逻辑——因为Observable已经自己结束了,所以你在ngOnDestroy里看到observers长度为0是完全正常的。
2. takeUntil的核心作用场景
takeUntil的真正价值是处理不会自动完成的长订阅,比如:
interval/timer这类定时发射的Observable- WebSocket连接的订阅
- 路由参数
ActivatedRoute.params的订阅 - 持续监听的状态流(比如NgRx store的select)
对于这些场景,Observable不会自动结束,订阅会一直存在,直到你调用takeUntil对应的Subject的next()方法,此时observers数组在ngOnDestroy时会有长度,调用next()后才会清空。
3. 你的代码里的小问题(虽不影响当前现象,但需修正)
注意到你代码里的Subject变量名拼写错误:ngUnsubscibe少了一个字母r,正确的应该是ngUnsubscribe。虽然这次因为变量名和调用时的拼写一致,没有导致功能问题,但这种拼写错误很容易在后续维护中引发bug,建议立即修正:
// 修正拼写 ngUnsubscribe: Subject<boolean> = new Subject(); // ngOnInit里也对应修正 this.carsService.getDetails(this.id) .takeUntil(this.ngUnsubscribe) .subscribe((car) => {this.car = car}, (err) => console.log(err) );
总结
- 对于HTTP这类单次Observable,
observers为空是正常现象,订阅已经自动完成销毁 - 你的
takeUntil逻辑是正确的,即使observers为空,调用next()和complete()也不会有任何副作用 - 记得修正变量名的拼写错误,避免后续潜在问题
内容的提问来源于stack exchange,提问作者Batsheva
相关产品推荐
相关产品推荐

