Angular 6 - 如何停止 subscribe() 中的无限轮询
Angular 6 - How to stop infinite polling in subscribe()
所以我想根据列表中的项目数是否大于 3 来显示一个图标。我正在使用这个 getProjects() 函数,我需要订阅它才能获取数据。我在订阅时设置了一个布尔值来检查列表中的项目数量,然后在我的 HTML 中,我使用 ngIf 来显示基于布尔值的图标。我能够让它正确显示,但是,我想我一直在我的订阅中进行轮询,并一遍又一遍地设置这个布尔值,因为它使我的网页 运行 非常慢。
我已经尝试了似乎不会停止订阅的 take(1) 方法,并将其设置为组件内的 "this.variable" 范围。我目前正在使用事件发射器,但它也不起作用。
到目前为止,这是我的代码,
我订阅的函数(在不同的组件中):
getProjects(): Observable<ProjectInterfaceWithId[]> {
const organizationId = localStorage.getItem('organizationId');
return this.firestoreService.collection('organizations').doc(organizationId)
.collection('projects').snapshotChanges()
.pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as ProjectInterface;
const id = a.payload.doc.id;
return {id, ...data} as ProjectInterfaceWithId;
})),
map(list => {
if (list.length !== 0) {
this.buildProjectLookup(list);
this.projects = list;
return list;
}
})
);
}
我用来获取数据和设置布尔值的函数:
@Input() toggle: boolean;
@Output() iconStatus = new EventEmitter();
displayIcon() {
this.projectService.getProjects()
.pipe(take(1))
.subscribe(
list => {
if(list.length >= 3){
this.toggle = true;
this.iconStatus.emit(this.toggle);
}
});
}
HTML:
<i *ngIf="displayIcon()" class="material-icons">list</i>
有没有什么办法让我只检查一次列表长度,这样我就不会陷入这个订阅循环?提前致谢!
它看起来可能是由于 ngIf 引用 displayIcon()
方法而发生的。
每次在您的组件中运行更改检测时,都会调用此方法。如果您的组件使用默认更改检测,这将非常频繁。
有关更多信息,请参阅 https://blog.angular-university.io/how-does-angular-2-change-detection-really-work/
解决这个问题的一种方法是让 ngIf 引用一个变量。
例如,您可以使用
设置一个 projects$
observable
this.projects$ = this.projectService.getProjects()
.pipe(
take(1),
tap(projects => this.iconStatus.emit(projects.length >= 3))
);
这个 observable 可能应该在您的 ngOnInit()
方法中实例化。
然后在你的模板中你可以使用
<i *ngIf="(projects$ | async)?.length >= 3" class="material-icons">list</i>
所以我想根据列表中的项目数是否大于 3 来显示一个图标。我正在使用这个 getProjects() 函数,我需要订阅它才能获取数据。我在订阅时设置了一个布尔值来检查列表中的项目数量,然后在我的 HTML 中,我使用 ngIf 来显示基于布尔值的图标。我能够让它正确显示,但是,我想我一直在我的订阅中进行轮询,并一遍又一遍地设置这个布尔值,因为它使我的网页 运行 非常慢。
我已经尝试了似乎不会停止订阅的 take(1) 方法,并将其设置为组件内的 "this.variable" 范围。我目前正在使用事件发射器,但它也不起作用。
到目前为止,这是我的代码,
我订阅的函数(在不同的组件中):
getProjects(): Observable<ProjectInterfaceWithId[]> {
const organizationId = localStorage.getItem('organizationId');
return this.firestoreService.collection('organizations').doc(organizationId)
.collection('projects').snapshotChanges()
.pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as ProjectInterface;
const id = a.payload.doc.id;
return {id, ...data} as ProjectInterfaceWithId;
})),
map(list => {
if (list.length !== 0) {
this.buildProjectLookup(list);
this.projects = list;
return list;
}
})
);
}
我用来获取数据和设置布尔值的函数:
@Input() toggle: boolean;
@Output() iconStatus = new EventEmitter();
displayIcon() {
this.projectService.getProjects()
.pipe(take(1))
.subscribe(
list => {
if(list.length >= 3){
this.toggle = true;
this.iconStatus.emit(this.toggle);
}
});
}
HTML:
<i *ngIf="displayIcon()" class="material-icons">list</i>
有没有什么办法让我只检查一次列表长度,这样我就不会陷入这个订阅循环?提前致谢!
它看起来可能是由于 ngIf 引用 displayIcon()
方法而发生的。
每次在您的组件中运行更改检测时,都会调用此方法。如果您的组件使用默认更改检测,这将非常频繁。
有关更多信息,请参阅 https://blog.angular-university.io/how-does-angular-2-change-detection-really-work/
解决这个问题的一种方法是让 ngIf 引用一个变量。 例如,您可以使用
设置一个projects$
observable
this.projects$ = this.projectService.getProjects()
.pipe(
take(1),
tap(projects => this.iconStatus.emit(projects.length >= 3))
);
这个 observable 可能应该在您的 ngOnInit()
方法中实例化。
然后在你的模板中你可以使用
<i *ngIf="(projects$ | async)?.length >= 3" class="material-icons">list</i>