ERROR: 'Error during cleanup of component', Object{component: FilterComponent
ERROR: 'Error during cleanup of component', Object{component: FilterComponent
我正在对 FilterComponent 进行测试,但每次我 运行 命令时都会收到此错误:
错误
'Error during cleanup of component', Object{component: FilterComponent{lang:
Language{cookie: ..., get: ..., getLocale: ..., dict: ...}, api: Api{http:
..., router: ..., cookie: ..., send: ..., setUrl: ...}, filterService:
FilterService{update: ..., filter: ...}, searchbar: SearchbarService{},
localStorageCache: LocalStorageCache{api: ...}, cookie: CookieService{document:
..., optionsProvider: ..., cookieWriterService: ..., options: ...}, formatter:
NgbDateISOParserFormatter{}, calendar: NgbCalendarGregorian{}, onFilter:
EventEmitter{_isScalar: ..., observers: ..., closed: ..., isStopped: ..., hasError:
..., thrownError: ..., __isAsync: ...}, category: '', search: Subject{_isScalar:
..., observers: ..., closed: ..., isStopped: ..., hasError: ..., thrownError: ...},
selectedElems: [], hoveredDate: null, filterDef: Object{tweets: ..., news: ..., events:
..., dashboard: ..., dashboardHashtags: ..., people: ..., reports: ..., editorials:
..., verdicts: ..., organizations: ..., results: ..., _dashboard: ...}, componentDict:
Object{author: ..., people: ..., organizations: ..., tag: ..., tactics: ..., court:
..., pillars: ..., hashtags: ..., magistrates: ..., website: ...}, yearRange: [..., ...],
getPillars: () => { ... }, dateFromNgbDate: ngbDate => { ... }, isEmpty: () => { ... },
getElements: () => { ... }, addItem: item => { ... }, compareIds: (el1, el2) => { ... },
clearItem: item => { ... }, fillMultiSelect: () => { ... }, relevantChange: $ev => {
... }, user: Object{id: ..., username: ..., name: ..., role: ..., id_client: ...,
language: ..., filter: ..., services: ...}, __ngContext__: [..., ..., ..., ..., ...,
..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ...,
..., ..., ..., ..., ..., ..., ..., ..., ...], filterObj: Object{date_range: ...,
relevant: ...}}, stacktrace: TypeError: Cannot read properties of undefined (reading 'unsubscribe')
TypeError: Cannot read properties of undefined (reading 'unsubscribe')
我已经通过导入组件使用的所有内容配置了规范文件。
filterComponent
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
import { Language } from '../../services/language.service';
import { Observable, concat, of, Subject, Subscription } from 'rxjs';
import { distinctUntilChanged, switchMap, filter } from 'rxjs/operators';
import { CookieService } from 'ngx-cookie';
import { Api } from '../../services/api.service';
import { FilterService } from '../../services/filter.service';
import { LocalStorageCache } from '../../services/local-storage-cache.service';
import * as _ from 'lodash';
import { SearchbarService } from '../../services/searchbar.service';
import { NgbDate, NgbCalendar, NgbDateParserFormatter } from '@ng-bootstrap/ng-bootstrap';
export interface MultiSelectItem {
id: number,
name: string,
type: string
}
@Component({
selector: 'is-filter',
templateUrl: './filter.component.html',
styleUrls: ['./filter.component.scss']
})
export class FilterComponent implements OnInit, OnDestroy {
@Input() type: string;
@Input() filterObj: any;
@Output() onFilter: EventEmitter<any> = new EventEmitter<any>();
category: string = '';
//Escucha cambios en el campo de texto
search: Subject<string> = new Subject<string>();
selectedElems: MultiSelectItem[] = [];
hoveredDate: NgbDate | null = null;
filterDef: object = {
dashboard: ['date_range', 'pillars'],
}
componentDict = {
author: { component: 'Agents' },
}
user: any;
yearRange = [2020, 2021];
constructor(
public lang: Language,
private api: Api,
public filterService: FilterService,
public searchbar: SearchbarService,
public localStorageCache: LocalStorageCache,
private cookie: CookieService,
public formatter: NgbDateParserFormatter,
private calendar: NgbCalendar
) {
this.user = JSON.parse(this.cookie.get('user'));
}
updateFilterSubscription: Subscription;
filterSubscription: Subscription;
ngOnDestroy() {
this.updateFilterSubscription.unsubscribe();
this.filterSubscription.unsubscribe();
}
ngOnInit() {
this.clearFilter();
this.filter();
switch (this.type) {
case 'male':
this.category = 'mens';
break;
case 'female':
this.category = 'woman';
break;
}
}
pillars: MultiSelectItem[];
getPillars = async (): Promise<void> => {
if (localStorage.getItem('pillars')) {
this.pillars = JSON.parse(localStorage.getItem('pillars'));
return;
}
let items = await this.api.send('Categories', 'get', filter ? { filter: filter } : {}).then((res: { data: any[], count: number }) => {
return res.data.map(el => {
return { id: el.id, name: el.name, type: 'Categories' }
});
});
localStorage.setItem('pillars', JSON.stringify(items));
this.pillars = items;
}
private ngbDateFromDate(date: Date) {
return NgbDate.from({ year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() });
}
private dateFromNgbDate = (ngbDate: { year: number, month: number, day: number }) => new Date(ngbDate.year, ngbDate.month - 1, ngbDate.day);
clearFilter() {
this.filterObj = {};
this.selectedElems = [];
_.each(this.filterDef[this.type], filter => {
switch (filter) {
case 'date_range':
let startDate = new Date();
let endDate = new Date();
startDate.setDate(startDate.getDate() - 14);
endDate.setHours(23);
endDate.setMinutes(59, 59);
this.filterObj[filter] = {
start_date: this.ngbDateFromDate(startDate),
end_date: this.ngbDateFromDate(endDate)
}
break;
case 'relevant':
this.filterObj[filter] = true;
break;
case 'pillars':
this.category = 'pillars';
break;
case 'country':
default:
break;
}
})
if (typeof this.user.filter == 'string') {
try {
this.filterObj = { ...this.filterObj, ...JSON.parse(this.user.filter) };
} catch {
console.error("malformed_user_filter", this.user.filter);
}
}
}
filter() {
if (Object.keys(this.filterObj).indexOf('pillars') !== -1) {
if (typeof this.filterObj['pillars'] !== "object") {
this.onFilter.emit({ ...this.filterObj, pillars: this.pillars.filter(el => el.id == this.filterObj['pillars']) });
} else {
this.onFilter.emit({ ...this.filterObj });
}
} else {
this.onFilter.emit({ ...this.filterObj });
}
}
isEmpty = () => Object.keys(this.filterObj).filter(key => ['date_range', 'relevant'].indexOf(key) === -1).length === 0;
getElements = async (): Promise<MultiSelectItem[]> => {
let component = this.componentDict[this.category].component;
let filter = this.componentDict[this.category].filter;
let category = this.category == 'author' ? 'agent' : this.category;
if (localStorage.getItem(category)) return JSON.parse(localStorage.getItem(category))
let items = await this.api.send(component, 'get', filter ? { filter: filter } : {}).then((res: { data: any[], count: number }) => {
return res.data.map(el => {
return { id: el.id, name: el.name, type: component }
});
});
localStorage.setItem(category, JSON.stringify(items));
return items;
}
multiselectEls = concat(
of([]),
this.search.pipe(
distinctUntilChanged(),
filter(() => true),
switchMap((term: string) => {
return this.localStorageCache.get(this.category).then(elements => elements.filter(el => el['name'] && term ? el['name'].toLowerCase().indexOf(term.toLowerCase()) !== -1 : false))
}),
)
) as Observable<MultiSelectItem[]>;
validateInput(currentValue: NgbDate | null, input: string): NgbDate | null {
const parsed = this.formatter.parse(input);
return parsed && this.calendar.isValid(NgbDate.from(parsed)) ? NgbDate.from(parsed) : currentValue;
}
onDateSelection(date: NgbDate) {
let dateRange = this.filterObj.date_range;
if (this.filterObj.relevant === false) {
this.filterObj.date_range.start_date = date;
this.filterObj.date_range.end_date = date;
return;
}
if (!dateRange.start_date && !dateRange.end_date) {
this.filterObj.date_range.start_date = date;
}
if (!!dateRange.start_date && (!!dateRange.end_date || date.before(dateRange.start_date))) {
this.filterObj.date_range = {
start_date: date,
end_date: null
}
return;
}
if (!!dateRange.start_date && (date.after(dateRange.start_date) || date.equals(dateRange.start_date))) {
this.filterObj.date_range.end_date = date;
let offset = !this.filterObj.relevant && typeof this.filterObj.relevant !== 'undefined' ? 0 : 31;
let d = this.dateFromNgbDate(date);
d.setDate(d.getDate() - offset);
let offsetDate = this.ngbDateFromDate(d);
dateRange.start_date = offsetDate.after(dateRange.start_date) ? offsetDate : dateRange.start_date;
return;
}
}
}
我在 ts 文件中导入并配置了所有必要的东西,但是每次我尝试启动 ng 测试命令时配置都失败。
规格:
import { FilterComponent } from "./filter.component";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
import { RouterTestingModule } from '@angular/router/testing';
import { CookieModule, CookieService } from 'ngx-cookie';
import { Api } from '../../services/api.service';
import { MultiSelectItem } from './filter.component';
import { NgbDate } from '@ng-bootstrap/ng-bootstrap';
import { FilterService } from '../../services/filter.service';
var user = {
"id": 1,
"username": "test",
}
var item:MultiSelectItem = {
id: 1,
name: 'item1',
type: 'text'
};
describe('filter Component', () => {
let component: FilterComponent;
let fixture: ComponentFixture<FilterComponent>;
let cookieService: CookieService;
let apiService: Api;
let filterService: FilterService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
RouterTestingModule,
CookieModule.forRoot()
],
declarations: [
FilterComponent,
],
providers: [
Api,
CookieService,
FilterService
],
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA]
}).compileComponents();
});
beforeEach( () => {
cookieService = TestBed.inject(CookieService);
cookieService.put('user', JSON.stringify(user));
fixture = TestBed.createComponent(FilterComponent);
component = fixture.componentInstance;
apiService = TestBed.inject(Api);
filterService = TestBed.inject(FilterService);
component.ngOnInit();
});
afterEach(() => {
component = null;
fixture = null;
cookieService.removeAll();
apiService = null;
filterService = null;
cookieService = null;
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('ngOnInit()', () => {
it('Should call clearFilter()', () => {
let spy1 = spyOn(component, 'clearFilter');
component.ngOnInit();
expect(spy1).toHaveBeenCalled();
});
it('Should call filter()', () => {
let spy1 = spyOn(component, 'filter');
component.ngOnInit();
expect(spy1).toHaveBeenCalled();
});
it('Should category to be equal magistrates', () => {
component.type = 'verdicts';
component.ngOnInit();
expect(component.category).toEqual('magistrates');
});
it('Should category to be equal hashtags', () => {
component.type = 'dashboardHashtags';
component.ngOnInit();
expect(component.category).toEqual('hashtags');
});
it('Should category to be equal people', () => {
component.type = '';
component.ngOnInit();
expect(component.category).toEqual('people');
});
it('Should call clearFilter() from ngOnInit next subscribe', () => {
let spy1 = spyOn(component, 'clearFilter');
component.ngOnInit();
expect(spy1).toHaveBeenCalled();
});
});
});
在您的测试中,您的订阅变量永远不会被分配,这会在 ngOnDestroy
函数中抛出您的错误。
要解决此问题,您可以像这样立即定义您的订阅:
updateFilterSubscription = new Subscription();
然后使用
添加您的订阅
this.updateFilterSubscription.add(<your_subscription>);
或者在您的 ngOnDestroy 函数中,您可以检查订阅是否存在,例如?
运算符,或者 if
如果您喜欢这种方式,然后像这样取消订阅
this.updateFilterSubscription?.unsubscribe();
我正在对 FilterComponent 进行测试,但每次我 运行 命令时都会收到此错误:
错误
'Error during cleanup of component', Object{component: FilterComponent{lang:
Language{cookie: ..., get: ..., getLocale: ..., dict: ...}, api: Api{http:
..., router: ..., cookie: ..., send: ..., setUrl: ...}, filterService:
FilterService{update: ..., filter: ...}, searchbar: SearchbarService{},
localStorageCache: LocalStorageCache{api: ...}, cookie: CookieService{document:
..., optionsProvider: ..., cookieWriterService: ..., options: ...}, formatter:
NgbDateISOParserFormatter{}, calendar: NgbCalendarGregorian{}, onFilter:
EventEmitter{_isScalar: ..., observers: ..., closed: ..., isStopped: ..., hasError:
..., thrownError: ..., __isAsync: ...}, category: '', search: Subject{_isScalar:
..., observers: ..., closed: ..., isStopped: ..., hasError: ..., thrownError: ...},
selectedElems: [], hoveredDate: null, filterDef: Object{tweets: ..., news: ..., events:
..., dashboard: ..., dashboardHashtags: ..., people: ..., reports: ..., editorials:
..., verdicts: ..., organizations: ..., results: ..., _dashboard: ...}, componentDict:
Object{author: ..., people: ..., organizations: ..., tag: ..., tactics: ..., court:
..., pillars: ..., hashtags: ..., magistrates: ..., website: ...}, yearRange: [..., ...],
getPillars: () => { ... }, dateFromNgbDate: ngbDate => { ... }, isEmpty: () => { ... },
getElements: () => { ... }, addItem: item => { ... }, compareIds: (el1, el2) => { ... },
clearItem: item => { ... }, fillMultiSelect: () => { ... }, relevantChange: $ev => {
... }, user: Object{id: ..., username: ..., name: ..., role: ..., id_client: ...,
language: ..., filter: ..., services: ...}, __ngContext__: [..., ..., ..., ..., ...,
..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ..., ...,
..., ..., ..., ..., ..., ..., ..., ..., ...], filterObj: Object{date_range: ...,
relevant: ...}}, stacktrace: TypeError: Cannot read properties of undefined (reading 'unsubscribe')
TypeError: Cannot read properties of undefined (reading 'unsubscribe')
我已经通过导入组件使用的所有内容配置了规范文件。
filterComponent
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
import { Language } from '../../services/language.service';
import { Observable, concat, of, Subject, Subscription } from 'rxjs';
import { distinctUntilChanged, switchMap, filter } from 'rxjs/operators';
import { CookieService } from 'ngx-cookie';
import { Api } from '../../services/api.service';
import { FilterService } from '../../services/filter.service';
import { LocalStorageCache } from '../../services/local-storage-cache.service';
import * as _ from 'lodash';
import { SearchbarService } from '../../services/searchbar.service';
import { NgbDate, NgbCalendar, NgbDateParserFormatter } from '@ng-bootstrap/ng-bootstrap';
export interface MultiSelectItem {
id: number,
name: string,
type: string
}
@Component({
selector: 'is-filter',
templateUrl: './filter.component.html',
styleUrls: ['./filter.component.scss']
})
export class FilterComponent implements OnInit, OnDestroy {
@Input() type: string;
@Input() filterObj: any;
@Output() onFilter: EventEmitter<any> = new EventEmitter<any>();
category: string = '';
//Escucha cambios en el campo de texto
search: Subject<string> = new Subject<string>();
selectedElems: MultiSelectItem[] = [];
hoveredDate: NgbDate | null = null;
filterDef: object = {
dashboard: ['date_range', 'pillars'],
}
componentDict = {
author: { component: 'Agents' },
}
user: any;
yearRange = [2020, 2021];
constructor(
public lang: Language,
private api: Api,
public filterService: FilterService,
public searchbar: SearchbarService,
public localStorageCache: LocalStorageCache,
private cookie: CookieService,
public formatter: NgbDateParserFormatter,
private calendar: NgbCalendar
) {
this.user = JSON.parse(this.cookie.get('user'));
}
updateFilterSubscription: Subscription;
filterSubscription: Subscription;
ngOnDestroy() {
this.updateFilterSubscription.unsubscribe();
this.filterSubscription.unsubscribe();
}
ngOnInit() {
this.clearFilter();
this.filter();
switch (this.type) {
case 'male':
this.category = 'mens';
break;
case 'female':
this.category = 'woman';
break;
}
}
pillars: MultiSelectItem[];
getPillars = async (): Promise<void> => {
if (localStorage.getItem('pillars')) {
this.pillars = JSON.parse(localStorage.getItem('pillars'));
return;
}
let items = await this.api.send('Categories', 'get', filter ? { filter: filter } : {}).then((res: { data: any[], count: number }) => {
return res.data.map(el => {
return { id: el.id, name: el.name, type: 'Categories' }
});
});
localStorage.setItem('pillars', JSON.stringify(items));
this.pillars = items;
}
private ngbDateFromDate(date: Date) {
return NgbDate.from({ year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() });
}
private dateFromNgbDate = (ngbDate: { year: number, month: number, day: number }) => new Date(ngbDate.year, ngbDate.month - 1, ngbDate.day);
clearFilter() {
this.filterObj = {};
this.selectedElems = [];
_.each(this.filterDef[this.type], filter => {
switch (filter) {
case 'date_range':
let startDate = new Date();
let endDate = new Date();
startDate.setDate(startDate.getDate() - 14);
endDate.setHours(23);
endDate.setMinutes(59, 59);
this.filterObj[filter] = {
start_date: this.ngbDateFromDate(startDate),
end_date: this.ngbDateFromDate(endDate)
}
break;
case 'relevant':
this.filterObj[filter] = true;
break;
case 'pillars':
this.category = 'pillars';
break;
case 'country':
default:
break;
}
})
if (typeof this.user.filter == 'string') {
try {
this.filterObj = { ...this.filterObj, ...JSON.parse(this.user.filter) };
} catch {
console.error("malformed_user_filter", this.user.filter);
}
}
}
filter() {
if (Object.keys(this.filterObj).indexOf('pillars') !== -1) {
if (typeof this.filterObj['pillars'] !== "object") {
this.onFilter.emit({ ...this.filterObj, pillars: this.pillars.filter(el => el.id == this.filterObj['pillars']) });
} else {
this.onFilter.emit({ ...this.filterObj });
}
} else {
this.onFilter.emit({ ...this.filterObj });
}
}
isEmpty = () => Object.keys(this.filterObj).filter(key => ['date_range', 'relevant'].indexOf(key) === -1).length === 0;
getElements = async (): Promise<MultiSelectItem[]> => {
let component = this.componentDict[this.category].component;
let filter = this.componentDict[this.category].filter;
let category = this.category == 'author' ? 'agent' : this.category;
if (localStorage.getItem(category)) return JSON.parse(localStorage.getItem(category))
let items = await this.api.send(component, 'get', filter ? { filter: filter } : {}).then((res: { data: any[], count: number }) => {
return res.data.map(el => {
return { id: el.id, name: el.name, type: component }
});
});
localStorage.setItem(category, JSON.stringify(items));
return items;
}
multiselectEls = concat(
of([]),
this.search.pipe(
distinctUntilChanged(),
filter(() => true),
switchMap((term: string) => {
return this.localStorageCache.get(this.category).then(elements => elements.filter(el => el['name'] && term ? el['name'].toLowerCase().indexOf(term.toLowerCase()) !== -1 : false))
}),
)
) as Observable<MultiSelectItem[]>;
validateInput(currentValue: NgbDate | null, input: string): NgbDate | null {
const parsed = this.formatter.parse(input);
return parsed && this.calendar.isValid(NgbDate.from(parsed)) ? NgbDate.from(parsed) : currentValue;
}
onDateSelection(date: NgbDate) {
let dateRange = this.filterObj.date_range;
if (this.filterObj.relevant === false) {
this.filterObj.date_range.start_date = date;
this.filterObj.date_range.end_date = date;
return;
}
if (!dateRange.start_date && !dateRange.end_date) {
this.filterObj.date_range.start_date = date;
}
if (!!dateRange.start_date && (!!dateRange.end_date || date.before(dateRange.start_date))) {
this.filterObj.date_range = {
start_date: date,
end_date: null
}
return;
}
if (!!dateRange.start_date && (date.after(dateRange.start_date) || date.equals(dateRange.start_date))) {
this.filterObj.date_range.end_date = date;
let offset = !this.filterObj.relevant && typeof this.filterObj.relevant !== 'undefined' ? 0 : 31;
let d = this.dateFromNgbDate(date);
d.setDate(d.getDate() - offset);
let offsetDate = this.ngbDateFromDate(d);
dateRange.start_date = offsetDate.after(dateRange.start_date) ? offsetDate : dateRange.start_date;
return;
}
}
}
我在 ts 文件中导入并配置了所有必要的东西,但是每次我尝试启动 ng 测试命令时配置都失败。
规格:
import { FilterComponent } from "./filter.component";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
import { RouterTestingModule } from '@angular/router/testing';
import { CookieModule, CookieService } from 'ngx-cookie';
import { Api } from '../../services/api.service';
import { MultiSelectItem } from './filter.component';
import { NgbDate } from '@ng-bootstrap/ng-bootstrap';
import { FilterService } from '../../services/filter.service';
var user = {
"id": 1,
"username": "test",
}
var item:MultiSelectItem = {
id: 1,
name: 'item1',
type: 'text'
};
describe('filter Component', () => {
let component: FilterComponent;
let fixture: ComponentFixture<FilterComponent>;
let cookieService: CookieService;
let apiService: Api;
let filterService: FilterService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
RouterTestingModule,
CookieModule.forRoot()
],
declarations: [
FilterComponent,
],
providers: [
Api,
CookieService,
FilterService
],
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA]
}).compileComponents();
});
beforeEach( () => {
cookieService = TestBed.inject(CookieService);
cookieService.put('user', JSON.stringify(user));
fixture = TestBed.createComponent(FilterComponent);
component = fixture.componentInstance;
apiService = TestBed.inject(Api);
filterService = TestBed.inject(FilterService);
component.ngOnInit();
});
afterEach(() => {
component = null;
fixture = null;
cookieService.removeAll();
apiService = null;
filterService = null;
cookieService = null;
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('ngOnInit()', () => {
it('Should call clearFilter()', () => {
let spy1 = spyOn(component, 'clearFilter');
component.ngOnInit();
expect(spy1).toHaveBeenCalled();
});
it('Should call filter()', () => {
let spy1 = spyOn(component, 'filter');
component.ngOnInit();
expect(spy1).toHaveBeenCalled();
});
it('Should category to be equal magistrates', () => {
component.type = 'verdicts';
component.ngOnInit();
expect(component.category).toEqual('magistrates');
});
it('Should category to be equal hashtags', () => {
component.type = 'dashboardHashtags';
component.ngOnInit();
expect(component.category).toEqual('hashtags');
});
it('Should category to be equal people', () => {
component.type = '';
component.ngOnInit();
expect(component.category).toEqual('people');
});
it('Should call clearFilter() from ngOnInit next subscribe', () => {
let spy1 = spyOn(component, 'clearFilter');
component.ngOnInit();
expect(spy1).toHaveBeenCalled();
});
});
});
在您的测试中,您的订阅变量永远不会被分配,这会在 ngOnDestroy
函数中抛出您的错误。
要解决此问题,您可以像这样立即定义您的订阅:
updateFilterSubscription = new Subscription();
然后使用
添加您的订阅this.updateFilterSubscription.add(<your_subscription>);
或者在您的 ngOnDestroy 函数中,您可以检查订阅是否存在,例如?
运算符,或者 if
如果您喜欢这种方式,然后像这样取消订阅
this.updateFilterSubscription?.unsubscribe();