基本上有两种情况:
通过使用async 管道,您只能在模板中使用可观察数据。在这种情况下,Angular 会处理订阅,并在组件被销毁时取消订阅。这里无事可做。
您可以在代码中手动订阅,方法是在该 observable 上调用 subscribe 方法。在这种情况下,您应该在组件被销毁时手动取消订阅。
要手动取消订阅,请使用 ngOnDestroy 生命周期挂钩:
import {OnDestroy} from '@angular/core'
@Component({...})
class MyComponent implements OnDestory {
// Component's code
constructor(private myService: MyService) {
this.subscription = myService.getData().subscribe(data => {...});
}
// Unsubscribe when the component is destroyed to avoid leaks.
ngOnDestroy() {
this.subscription.unsubscribe()
}
}
在某些情况下,当 observables 自己触发 finish 信号时,您可以避免取消订阅它们,但由于它通常是异步的,并且您无法确定它在您的组件被销毁之前发生,因此最好手动处理。
如果您对服务的 observable 是否结束感兴趣,可以使用带有三个参数的 do 运算符。
@Injectable()
export default class TestService {
stream: Observable<number>;
constructor() {
this.stream = Observable.interval(1000)
.do(
data => console.log(data),
error => console.log(error),
() => console.log('FINISH') // On finish, all subscriptions will be disposed automatically
);
}
.subscribe 也是如此。您可以使用组件中的第三个回调来记录流何时结束。
更新:
我想另一种提问方式是 UserAppModel
在提供者中列出时实例化
组件,然后当该组件“离开”时以某种方式销毁?
您的服务仍将每秒执行这些操作。您可以在订阅中尝试console.log 的某些内容以查看这种情况。这真的就像在计划JS中设置超时一样。该函数将无限存在,并且可以访问服务实例,从而防止它被垃圾收集。
作为旁注,我认为通过订阅 observables 来产生副作用是组件的角色,而不是服务的角色。这就是为什么他们首先有生命周期钩子。您可以考虑仅公开您的服务中的可观察对象,并在您的服务中管理订阅。这样您就不会遇到潜在的内存泄漏问题。
export class UserAppModel {
constructor(private requestQueue: RequestQueue) {}
startFetchingData() {
// As a bonus, if your requestQueue.enqueue is also an observable object,
// you could just merge it together to even better control
// the data (requests get cancelled when there's no active subscription)
return Observable.interval(1000).mergeMap(() => {
this.requestQueue.enqueue(aRequest);
});
}
}
class Component {
ngOnInit() {
this.subscription = this.userModel.startFetchingData().subscribe(data => {...})
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}