延迟角度旋转而不闪烁

问题描述 投票:0回答:2

目前我正在尝试使用 Angular HttpInterceptor 来显示一个旋转器once,这样每次 HttpRequest 完成时它就不会闪烁。我当前的 Interceptor.service.ts 代码如下所示:

@Injectable()
export class InterceptorService implements HttpInterceptor {
  constructor(private spinnerService: SpinnerService) {}

  showSpinner() {
    this.spinnerService.show.next(true);
    console.log('true');
  }

  hideSpinner() {
    this.spinnerService.show.next(false);
    console.log('false');
  }

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler,
  ): Observable<HttpEvent<any>> {
    const responseTimer$ = next
      .handle(req)
      .pipe(filter(e => e instanceof HttpResponse));
    timer(300)
      .pipe(takeUntil(responseTimer$))
      .subscribe(() => this.showSpinner());

    return next.handle(req).pipe(
      tap(evt => {
        if (evt instanceof HttpResponse) {
          this.hideSpinner();
        }
      }),
    );
  }
}

但是如果我尝试这段代码,控制台会说:

interceptor.service.ts:20 true
interceptor.service.ts:25 false
4 x interceptor.service.ts:20 true
4 x interceptor.service.ts:25 false
5 x interceptor.service.ts:25 false
interceptor.service.ts:25 false

但在我看来,它应该是 x 次正确,最后错误。我希望你明白我想要实现的目标。

javascript angular typescript spinner angular-http-interceptors
2个回答
2
投票

您的拦截器服务中需要一个计数器,它显示待处理请求的数量。当数字 >0 时,您会显示微调器。


编辑:

只是文本编辑器的理论

@Injectable()
export class InterceptorService implements HttpInterceptor {
  pendingCount$: BehaviorSubject<number> = new BehaviorSubject(0);

  constructor(private spinnerService: SpinnerService) {
    this.pendingCount$.pipe(
      map(Boolean),
      distinctUntilChanged(),
    ).subscribe(
      show => this.spinnerService.show.next(show),
    );
  }

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler,
  ): Observable<HttpEvent<any>> {
  
    this.pendingCount$.next(this.pendingCount$.value + 1);

    return next.handle(req).pipe(
      tap(evt => this.pendingCount$.next(this.pendingCount$.value - 1)),
    );
  }
}

1
投票

创建自己的

Subject
会更容易,它将跟踪已发出的请求数量,然后在跟踪计数低于零时抛出错误,从而避免错误。

class BusySubject extends Subject<number> {
    private _previous: number = 0;

    public next(value: number) {
        this._previous += value;
        if (this._previous < 0) {
            throw new Error('unexpected negative value');
        }
        return super.next(this._previous);
    }
}

以上是一个将超时值与安全检查相加以低于零的主题。

然后您可以在拦截器中使用它

@Injectable()
export class BusyInterceptor implements HttpInterceptor {

    private _requests: BusySubject = new BusySubject();

    public get busy(): Observable<boolean> {
        return this._requests.pipe(
            map((requests: number) => Boolean(requests)),
            distinctUntilChanged(),
        );
    }

    public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this._requests.next(1);
        return next.handle(req).pipe(finalize(() => this._requests.next(-1)));
    }
}

值得注意的是,在上面我使用

distinctUntilChanged()
作为繁忙指示器,并且还使用
finalize()
作为减少触发器。这些对于跟踪正确的忙碌状态很重要。

上述应该有效,无论何时您订阅忙碌。由于

_previous
值是主体的内部状态。即使没有订阅任何内容,它也应该继续正确跟踪。它的工作原理有点像
BehaviorSubject()
,只不过它使用
+=
来应用更改。

© www.soinside.com 2019 - 2024. All rights reserved.