Angular 中何时取消订阅
你可能知道当你订阅 Observable 对象或设置事件监听时,在某个时间点,你需要执行取消订阅操作,进而释放操作系统的内存。否则,你的应用程序可能会出现内存泄露。 接下来让我们看一下,需要在 手动释放资源场景表单export class TestComponent { ngOnInit() { this.form = new FormGroup({...}); // 监听表单值的变化 this.valueChanges = this.form.valueChanges.subscribe(console.log); // 监听表单状态的变化 this.statusChanges = this.form.statusChanges.subscribe(console.log); } ngOnDestroy() { this.valueChanges.unsubscribe(); this.statusChanges.unsubscribe(); } } 以上方案也适用于其它的表单控件。 路由export class TestComponent { constructor(private route: ActivatedRoute,private router: Router) { } ngOnInit() { this.route.params.subscribe(console.log); this.route.queryParams.subscribe(console.log); this.route.fragment.subscribe(console.log); this.route.data.subscribe(console.log); this.route.url.subscribe(console.log); this.router.events.subscribe(console.log); } ngOnDestroy() { // 手动执行取消订阅的操作 } } Renderer 服务export class TestComponent { constructor( private renderer: Renderer2,private element : ElementRef) { } ngOnInit() { this.click = this.renderer .listen(this.element.nativeElement,"click",handler); } ngOnDestroy() { this.click.unsubscribe(); } } Infinite Observables当你使用 export class TestComponent { constructor(private element : ElementRef) { } interval: Subscription; click: Subscription; ngOnInit() { this.interval = Observable.interval(1000).subscribe(console.log); this.click = Observable.fromEvent(this.element.nativeElement,'click') .subscribe(console.log); } ngOnDestroy() { this.interval.unsubscribe(); this.click.unsubscribe(); } } Redux Storeexport class TestComponent { constructor(private store: Store) { } todos: Subscription; ngOnInit() { /** * select(key : string) { * return this.map(state => state[key]).distinctUntilChanged(); * } */ this.todos = this.store.select('todos').subscribe(console.log); } ngOnDestroy() { this.todos.unsubscribe(); } } 无需手动释放资源场景AsyncPipe@Component({ selector: 'test',template: `<todos [todos]="todos$ | async"></todos>` }) export class TestComponent { constructor(private store: Store) { } ngOnInit() { this.todos$ = this.store.select('todos'); } } 当组件销毁时, Angular AsyncPipe 源码片段 @Pipe({name: 'async',pure: false}) export class AsyncPipe implements OnDestroy,PipeTransform { // ... constructor(private _ref: ChangeDetectorRef) {} ngOnDestroy(): void { if (this._subscription) { this._dispose(); } } } @HostListenerexport class TestDirective { @HostListener('click') onClick() { .... } } 需要注意的是,如果使用 @HostListener 装饰器,添加事件监听时,我们无法手动取消订阅。如果需要手动移除事件监听的话,可以使用以下的方式: // subscribe this.handler = this.renderer.listen('document',event =>{...}); // unsubscribe this.handler(); Finite Observable当你使用 export class TestComponent { constructor(private http: Http) { } ngOnInit() { // 表示1s后发出值,然后就结束了 Observable.timer(1000).subscribe(console.log); this.http.get('http://api.com').subscribe(console.log); } } timer 操作符
public static timer(initialDelay: number | Date,period: number,scheduler: Scheduler): Observable
// 每隔1秒发出自增的数字,3秒后开始发送 var numbers = Rx.Observable.timer(3000,1000); numbers.subscribe(x => console.log(x)); // 5秒后发出一个数字 var numbers = Rx.Observable.timer(5000); numbers.subscribe(x => console.log(x)); 最终建议你应该尽可能少的调用 具体示例如下: export class TestComponent { constructor(private store: Store) { } private componetDestroyed: Subject = new Subject(); todos: Subscription; posts: Subscription; ngOnInit() { this.todos = this.store.select('todos') .takeUntil(this.componetDestroyed).subscribe(console.log); this.posts = this.store.select('posts') .takeUntil(this.componetDestroyed).subscribe(console.log); } ngOnDestroy() { this.componetDestroyed.next(); this.componetDestroyed.unsubscribe(); } } takeUntil 操作符
public takeUntil(notifier: Observable): Observable<T>
发出源 Observable 发出的值,直到
var interval = Rx.Observable.interval(1000); var clicks = Rx.Observable.fromEvent(document,'click'); var result = interval.takeUntil(clicks); result.subscribe(x => console.log(x)); 参考资源
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |