【问题标题】:Loader interceptor hides the loader before getting response in angular加载程序拦截器在获得角度响应之前隐藏加载程序
【发布时间】:2019-06-18 16:36:14
【问题描述】:

我在我的 Angular 项目中使用 HTTP 拦截器显示加载栏,每当 HTTP 请求发送到服务时,它都会显示加载器。

loader.service.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class LoaderService {

  isLoading = new Subject<boolean>();

  constructor() { }

  show() {

    this.isLoading.next(true);
  }

  hide() {

    this.isLoading.next(false);
  }

}

loader-interceptor.ts

import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
import { finalize } from 'rxjs/operators';

import { LoaderService } from '../services/loader.service';

@Injectable()
export class LoaderInterceptorService implements HttpInterceptor {

  constructor(private loaderService: LoaderService) { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    this.loaderService.show();
    return next.handle(request).pipe( finalize( () => this.loaderService.hide()) );
  }

}

问题是加载器在数据加载之前隐藏。尤其是在有大量数据的情况下会发生这种情况。我希望加载程序不要隐藏,除非所有请求都已解决,否则用户无法与表单等交互,除非数据已加载。加载器 HTML 使用覆盖 CSS 来阻止用户与表单交互,直到数据到达。

在另一个项目中,当我订阅每个组件中的服务方法时,我曾经在服务调用中调用这些隐藏/显示方法。我想避免这种情况,因为这需要我在每个组件中一次又一次地添加此代码。

这个问题有什么解决办法吗?

PS: 当不同组件同时存在多个 HTTP 请求时,处理 loader 是否有问题?

【问题讨论】:

  • 奇怪,这应该可以。你可以试试“return next.handle(request).pipe(tap((event: HttpEvent) => { if (event instanceof HttpResponse) { this.loaderService.hide(); } );”跨度>
  • @riorudo。我会检查这个。我想知道问题的原因。
  • 似乎您将加载程序隐藏在请求本身中,应该指定拦截响应

标签: angular


【解决方案1】:

由于多个异步 API 调用,我也面临同样的问题。 但是我写了不同的逻辑。所以想在这里分享也许它会对某人有所帮助。

我希望您已经创建了一个您订阅 isLoading 状态的加载器组件。

所以在那个组件中创建 一个变量

showLoader: boolean[] = [];

在订阅者内部,而不是分配该真/假值,只需对布尔数组执行推送或弹出操作(代码如下)。

在您的 HTML 中,您可以通过检查数组的长度来显示/隐藏您的加载器 例如this.showLoader.length

this.LoaderService.isLoading.subscribe((val: boolean) => {
      if (val){
          this.showLoader.push(val);
        } else {
          this.showLoader.pop();
        }
    })

谢谢。

【讨论】:

  • 是的,如果您同时调用多个 api,这很有用
【解决方案2】:

您应该在响应时隐藏加载程序:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.loaderService.show();
    return next.handle(req).pipe(map(event => {
        if (event instanceof HttpResponse) {
           this.loaderService.hide();
        }         
        return event;
    }));
}

【讨论】:

  • 是的。我已经尝试过,但这不起作用。我想弄清楚我的实现有什么问题。
  • @Jeol,我试图 console.log((event instanceof HttpResponse)) 并且它总是给出错误并陷入无限循环。
  • 它已修复。谢谢
【解决方案3】:

如果我们有多个 api 调用,那么请使用这个..

导出类 LoaderInterceptor 实现 HttpInterceptor {

showLoaderCustom: any[] = [];
constructor(private loaderService: LoaderService) { }

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
   
    this.loaderService.show();
    this.showLoaderCustom.push(request);
    return next.handle(request).pipe(tap((event: HttpEvent<any>) => {
        if (event instanceof HttpResponse) {
            this.showLoaderCustom.pop();
            if(this.showLoaderCustom.length == 0){
                this.loaderService.hide();
            }
        }
    },
        (err: any) => {
            this.showLoaderCustom.pop();
            if(this.showLoaderCustom.length == 0){
                this.loaderService.hide();
            }
        }));
}   

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 2017-05-08
    • 2016-06-13
    • 2010-10-02
    • 2011-09-01
    • 2019-07-22
    相关资源
    最近更新 更多