你可能知道当你订阅 Observable 对象或设置事件监听时,在某个时间点,你需要执行取消订阅操作,进而释放操作系统的内存。否则,你的应用程序可能会出现内存泄露。
接下来让我们看一下,需要在 ngOnDestroy 生命周期钩子中,手动执行取消订阅操作的一些常见场景。本文主要介绍了浅谈Angular 中何时取消订阅,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能帮助到大家。
手动释放资源场景
表单
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
当你使用 interval() 或 fromEvent() 操作符时,你创建的是一个无限的 Observable 对象。这样的话,当我们不再需要使用它们的时候,就需要取消订阅,手动释放资源。
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 Store
export 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'); } }
当组件销毁时,async 管道会自动执行取消订阅操作,进而避免内存泄露的风险。
Angular AsyncPipe 源码片段
@Pipe({name: 'async', pure: false}) export class AsyncPipe implements OnDestroy, PipeTransform { // ... constructor(private _ref: ChangeDetectorRef) {} ngOnDestroy(): void { if (this._subscription) { this._dispose(); } } }
@HostListener
export class TestDirective { @HostListener('click') onClick() { .... } }
需要注意的是,如果使用 @HostListener 装饰器,添加事件监听时,我们无法手动取消订阅。如果需要手动移除事件监听的话,可以使用以下的方式:
// subscribe this.handler = this.renderer.listen('document', "click", event =>{...}); // unsubscribe this.handler();
Finite Observable
当你使用 HTTP 服务或 timer 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
操作符作用
timer 返回一个发出无限自增数列的 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));
最终建议
你应该尽可能少的调用 unsubscribe() 方法,你可以在RxJS: Don't Unsubscribe 这篇文章中了解与 Subject 相关更多信息。
具体示例如下:
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 发出的值,直到 notifier 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));
相关推荐:
详解AngularJS中自定义指令的使用_AngularJS
以上是详解Angular 中何时取消订阅的详细内容。更多信息请关注PHP中文网其他相关文章!

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。 1.Python以简洁语法和丰富库生态着称,适用于数据分析和Web开发。 2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

JavaScript不需要安装,因为它已内置于现代浏览器中。你只需文本编辑器和浏览器即可开始使用。1)在浏览器环境中,通过标签嵌入HTML文件中运行。2)在Node.js环境中,下载并安装Node.js后,通过命令行运行JavaScript文件。

如何在Quartz中提前发送任务通知在使用Quartz定时器进行任务调度时,任务的执行时间是由cron表达式设定的。现�...


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

Dreamweaver Mac版
视觉化网页开发工具

记事本++7.3.1
好用且免费的代码编辑器