博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【译】Angular自动取消订阅
阅读量:6510 次
发布时间:2019-06-24

本文共 3719 字,大约阅读时间需要 12 分钟。

  • 原文链接:https://netbasal.com/automagically-unsubscribe-in-angular-4487e9853a88
  • 创建时间:2018-06-18
  • 修改时间:2018-06-20
  • 参与人员:@Zaynex,@我爱吃南瓜

如你所知,当你在 Javascript 中订阅一个 observable 或者事件时,你通常需要在特定的时候取消订阅以释放内存。否则,就会导致

A memory leak occurs when a section of memory that is no longer being used is still being occupied needlessly instead of being returned to the OS

当一部分内存不再使用但它仍被不必要得占用而不是返回给操作系统时就会产生内存泄漏。

在 Angular 的组件或者指令中,你需要在 ngOnDestroy 的生命周期中 unsubscribe。

比如,如果你有一个组件,它有2个订阅源。

@Component({  selector: 'test',  template: `...`,})export class TestComponent {  one$;  two$;  constructor( private store: Store
, private element : ElementRef ) {} ngOnInit() { this.one$ = store.select("data").subscribe(data => // do something); this.two$ = Observable.interval(1000).subscribe(data => // do something); } ngOnDestroy() { this.one$.unsubscribe(); this.two$.unsubscribe(); }}复制代码

你需要创建 ngOnDestroy 的方法并且给每个订阅源取消订阅。

这很不错,但是我想要这些取消订阅的过程自动化。如果我可以创建一个 decorator 类去帮我做这个事情会怎样呢? 我们假设它会像下面这样:

@Component({  selector: 'test',  template: `...`,})@AutoUnsubscribeexport class TestComponent {  one$;  two$  three;  constructor( private store: Store
, private element : ElementRef) {} ngOnInit() { //...same subscriptions } // Notice that we don't have the ngOnDestroy method anymore}复制代码

让我们创建一个类装饰器并且给它命名为 AutoUnsubscribe

TypescriptBabel 中, 类装饰器仅仅是一个接受一个参数的、被装饰的类的构造函数。 (a class decorator is just a function that takes one parameter, the constructor of the decorated class.)

类装饰器作用于类的 constructor,并且观察、修改或者替换一个类的定义。

export function AutoUnsubscribe( constructor ) {  const original = constructor.prototype.ngOnDestroy;  constructor.prototype.ngOnDestroy = function () {    for ( let prop in this ) {      const property = this[ prop ];      if ( property && (typeof property.unsubscribe === "function") ) {        property.unsubscribe();      }    }    original && typeof original === "function" && original.apply(this, arguments);  };}复制代码

? 这里于三个简单的步骤:

  1. 保存一个引用指向原来的 ngOnDestory 函数。
  2. 创建你自己的 ngOnDestroy,循环遍历类的属性并且调用 unsubscribe 函数,如果存在的话。
  3. 调用原来的 ngOndestroy 函数

? 但是... 等等,如果因为某些疯狂的理由,你仍需要保留订阅源呢?比如当组件注销的时候你并不想取消订阅 $two 这个订阅源。

这种情况下我们需要传入一个参数给装饰器(一个数组用来过滤自动订阅),所以我们需要使用Decorator Factory

A Decorator Factory is simply a function that returns the expression that will be called by the decorator at runtime. 一个装饰器工厂就是一个函数,它会返回的运行期间被装饰器调用的函数。

export function AutoUnsubscribe(blackList = []) {  return function(constructor) {    const original = constructor.prototype.ngOndestroy;    constructor.prototype.ngOndestroy = function() {      for(let prop in this) {        const property = this[prop];        if(!blackList.includes(prop)) {          if(property && (typeof property.unsubscribe === 'function')) {            property.unsubscribe();          }        }      }      original && typeof original === 'function' && origin.apply(this, arguments);    };  }}复制代码

我们只是针对属性名做了检测,如果它不在 blacklist 的名单里那我们就调用 unsubscribe()

现在我们可以像这样使用 decorator:

@AutoUnsubscribe(["one$", "two$"])class TestComponent {  ...}复制代码

? 现在我们完成了! 你可以在这里找到,如果你有更好的想法,欢迎 pull request。

如果你想要更加声明式的方式在 中使用,你可以查看我的 class decorator,它有能力去做到:

import TakeUntilDestroy from "angular2-take-until-destroy";@Component({  selector: 'app-inbox',  templateUrl: './inbox.component.html'})@TakeUntilDestroyexport class InboxComponent {  componentDestroy;  constructor( ) {    const timer$ = Observable.interval(1000)      .takeUntil(this.componentDestroy())      .subscribe(val => console.log(val))    const timer2$ = Observable.interval(2000)      .takeUntil(this.componentDestroy())      .subscribe(val => console.log(val))  }}复制代码

不要害怕看源码,它就那么几行! 如果你喜欢这篇文档,查看我之前的一篇————

总结

你可以利用装饰器为你的应用添加强大的功能。 装饰器不是一个库也不是框架,所以要善于创造并利用好他们。 你可以探索更多的 decorators,

转载地址:http://erbfo.baihongyu.com/

你可能感兴趣的文章
#define WIN32_LEAN_AND_MEAN 的作用
查看>>
仿余额宝数字跳动效果 TextCounter
查看>>
你必须知道的.net学习总结
查看>>
Axure8.0 网页 or App 鼠标滚动效果
查看>>
大家好,新年快乐。
查看>>
在相同的主机上创建一个duplicate数据库
查看>>
Date15
查看>>
从Date类型转为中文字符串
查看>>
基于multisim的fm调制解调_苹果开始自研蜂窝网调制解调器 最快2024年能用上?
查看>>
mupdf不支持x64_Window权限维持(七):安全支持提供者
查看>>
labview如何弹出提示窗口_LabVIEW开发者必读的问答汇总,搞定疑难杂症全靠它了!...
查看>>
hikariconfig mysql_HikariConfig配置解析
查看>>
mysql批量数据多次查询数据库_mysql数据库批量操作
查看>>
jquery 乱码 传参_jquery获取URL中参数解决中文乱码问题的两种方法
查看>>
JDBC_MySQL_jdbc连接mysql_MySQL
查看>>
zcu106 固化_xilinx zcu106 vcu demo
查看>>
java ftpclient 代码_java后台代码ftpclient下载文件
查看>>
java数据库生成model_继承BaseModelGenerator 生成Model时添加数据库表字段 生成代码示例...
查看>>
smarty使用php代码,笑谈配置,使用Smarty技术_php
查看>>
silk v3 decoder php,解码转换QQ微信的SILK v3编码音频为MP3或其他格式
查看>>