在 ngoninit 中使用异步管道
我的角度应用程序中有许多 api 调用,如果数据来自服务器,我想在其中显示加载组件。
为此,我有一个像这样的加载器服务:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class LoaderService {
isLoading = new Subject<boolean>();
show() {
this.isLoading.next(true);
}
hide() {
this.isLoading.next(false);
}
}
我也有一个 httpInterceptor
,我在其中使用 show
和 hide
方法,如下所示
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
this.loaderService.show();
return new Observable((observer) => {
next.handle(request).subscribe(
(res) => {
observer.next(res);
},
(err: HttpErrorResponse) => {
this.loaderService.hide();
if (err.error.message) {
this.customNotificationService.showNotification(
err.error.message,
3000,
'error'
);
} else {
this.customNotificationService.showNotification(
'Ismeretlen eredetű hiba. Lépj kapcsolatba a rendszer üzemeltetőjével.',
3000,
'error'
);
}
},
() => {
this.loaderService.hide();
}
);
});
}
:组件,我想在其中使用加载组件,我在模板中有这个:
<loading-overlay
[visible]="loadingOverlayVisible | async"
loadingText=""
></loading-overlay>
并且在 ts 中:
loadingOverlayVisible: Subject<boolean> = this.loaderService.isLoading;
除了一种情况之外,此方法有效:ngOnInit
。当组件加载时,我会像这样加载初始数据:
ngOnInit() {
this.gridData = { data: [], total: 0 };
this.userService.getUsers().subscribe((users) => {
users.forEach((user) => {
// we get this as string from the backend
user.lastLoginDateDisplay = new Date(user.lastLoginDateDisplay!);
});
this.gridData = { data: users, total: users.length };
});
}
数据已加载,但没有任何加载指示器。如果我更改逻辑并使用标准的 subscribe
/unsubscribe
方式,它就可以工作。但使用异步管道会更干净/更智能。
那么,问题是:如何做到这一点?
I have in my angular app many api calls, where I want to show a loading component, if data is coming from server.
For this I have a loader service like this:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class LoaderService {
isLoading = new Subject<boolean>();
show() {
this.isLoading.next(true);
}
hide() {
this.isLoading.next(false);
}
}
I have an httpInterceptor
too, where I use the show
and hide
methods like this:
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
this.loaderService.show();
return new Observable((observer) => {
next.handle(request).subscribe(
(res) => {
observer.next(res);
},
(err: HttpErrorResponse) => {
this.loaderService.hide();
if (err.error.message) {
this.customNotificationService.showNotification(
err.error.message,
3000,
'error'
);
} else {
this.customNotificationService.showNotification(
'Ismeretlen eredetű hiba. Lépj kapcsolatba a rendszer üzemeltetőjével.',
3000,
'error'
);
}
},
() => {
this.loaderService.hide();
}
);
});
}
In the component, where I want to use the loading component, I have this in the template:
<loading-overlay
[visible]="loadingOverlayVisible | async"
loadingText=""
></loading-overlay>
And in the ts:
loadingOverlayVisible: Subject<boolean> = this.loaderService.isLoading;
This works except one case: ngOnInit
. When the component loads, I load the initial data like this:
ngOnInit() {
this.gridData = { data: [], total: 0 };
this.userService.getUsers().subscribe((users) => {
users.forEach((user) => {
// we get this as string from the backend
user.lastLoginDateDisplay = new Date(user.lastLoginDateDisplay!);
});
this.gridData = { data: users, total: users.length };
});
}
The data gets loaded, but without any loading indicator. If I change the logic and use the standard subscribe
/unsubscribe
way, it works. But it would be more cleaner/smarter with the async pipe.
So, the question is: how to do that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
LoaderService.isLoading 应该是BehaviorSubject。我不确定,但我认为 ngInit 在首次评估模板之前完成。如果我是对的,那么 LoaderService.isLoading 已经发出 true,当您的异步管道订阅时,为时已晚。
LoaderService.isLoading should be a BehaviorSubject instead. I'm not sure, but I think ngInit finishes before the template is first evaluated. If I'm right, then LoaderService.isLoading has already emitted true, and when your async pipe subscribes, it's too late.