Для предотвращения мерцания индикатора загрузки (я пропустил обработку нескольких запросов).
@Injectable()
export class LoadingInterceptor implements HttpInterceptor {
constructor(private spinnerService: SpinnerService) {}
intercept(req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> {
this.spinnerService.start();
return next.handle(req).pipe(finalize( () => this.spinnerService.stop()));
}
}
debounceTime (500) в сервисе spinner делает свое дело:
export class SpinnerService {
private readonly state = new BehaviorSubject<boolean>(true);
readonly state$ = this.state.asObservable()
.pipe(
debounceTime(500),
distinctUntilChanged()
);
constructor() {}
public start() {
this.state.next(true);
}
public stop() {
this.state.next(false);
}
}
Компонент, чтобы увидеть это в действии:
export interface Post {
id: string;
title: string;
body: string;
}
@Component({
selector: 'app-posts',
templateUrl: './posts.component.html',
styleUrls: ['./posts.component.css'],
})
export class PostsComponent implements OnInit {
readonly posts$: Observable<Post[]> = this.httpClient
.get<Post[]>('https://jsonplaceholder.typicode.com/posts')
.pipe(shareReplay(1));
readonly state$ = this.spinnerService.state$;
constructor(
private spinnerService: SpinnerService,
private httpClient: HttpClient
) {}
ngOnInit() {}
}
HTML:
<p>List of Posts</p>
<ng-container *ngIf="(state$ | async); else printResult">
<h1>Loading...</h1>
</ng-container>
<ng-template #printResult>
<ng-container *ngIf="posts$ | async as posts">
<p *ngFor="let post of posts">
{{ post.title }}
</p>
</ng-container>
</ng-template>
Решение с помощью перехватчика несколько крупнозернистое. В какой-то момент вам может понадобиться более мелкозернистое решение. Например, чтобы показать индикатор загрузки для нескольких параллельных запросов / компонентов. Другое решение дано в сообщении в блоге Нила .
Существует множество вариантов решения вашей проблемы. Надеюсь, это поможет.