使用ngx-ui-loader在Angular中连续发出多个http请求时,只设置单个加载器。

huangapple go评论68阅读模式
英文:

Set only single loader while hitting multiple http requests continuously using ngx-ui-loader in angular

问题

我已经实现了ngx-ui-loader并为每个HTTP请求启用了NgxUiLoaderHttpModule,它运行良好。但问题在于我的项目的某些路由上,会连续执行多个HTTP请求,并且加载器会在每个请求之后启动并在响应后停止,然后再为下一个请求重新启动,这看起来很不美观。所以是否有办法只显示一个加载器,用于所有连续的HTTP请求?

提前感谢!
我尝试了各种方法,但都没有成功。

英文:

I have implemented this ngx-ui-loader and set the NgxUiLoaderHttpModule for every HTTP request hits and it is working fine. But the issue is on some routes of my project, there are continuously multiple HTTP requests executed, and the loader start for every requests and stops after the response and then again starts for next request which looks awful. So is there any way to show only single loader for all continuous HTTP requests?

Thanks in advance!

I have tried various method but it didn't work.

答案1

得分: 2

以下是翻译好的部分:

@sfelli提出的解决方案很简单,但如果多个请求同时结束,可能会遇到问题。
`this.ngxService.stop()` 可能会被多次调用或者从未被调用 :-(
我找到的解决此问题的方法是使用RxJs的NEVER可观察对象。
下面是拦截器的重构代码:

import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { NgxUiLoaderService } from 'ngx-ui-loader';
import { catchError, finalize } from 'rxjs/operators';

@Injectable()
export class NgxHttpInterceptor implements HttpInterceptor {

  constructor(private readonly ngxService: NgxUiLoaderService) { }

  private readonly spinner$ = defer(() => {
    this.ngxService.start();
    return NEVER.pipe(
      finalize(() => {
        this.ngxService.stop();
      })
    );
  }).pipe(share());

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const spinnerSubscription: Subscription = this.spinner$.subscribe();
    return next.handle(req).pipe(finalize(() => spinnerSubscription.unsubscribe()));
  }
}

我做了一篇更深入描述这个解决方案的文章:在处理HTTP请求并发时显示加载器

英文:

The solution proposed by @sfelli is easy but you may face issue if multiple requests end in the same time.
this.ngxService.stop() may be called mutiple times or never called 使用ngx-ui-loader在Angular中连续发出多个http请求时,只设置单个加载器。
The solution I found to overcome this issue is to use RxJs NEVER observable.
Hereafter is a refactoring of the interceptor :

import { Injectable } from &#39;@angular/core&#39;;
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from &#39;@angular/common/http&#39;;
import { Observable, of } from &#39;rxjs&#39;;
import { NgxUiLoaderService } from &#39;ngx-ui-loader&#39;;
import { catchError, finalize } from &#39;rxjs/operators&#39;;

@Injectable()
export class NgxHttpInterceptor implements HttpInterceptor {

  constructor(private readonly ngxService: NgxUiLoaderService) { }

  private readonly spinner$ = defer(() =&gt; {
    this.ngxService.start();
    return NEVER.pipe(
      finalize(() =&gt; {
        this.ngxService.stop();
      })
    );
  }).pipe(share());

  intercept(req: HttpRequest&lt;any&gt;, next: HttpHandler): Observable&lt;HttpEvent&lt;any&gt;&gt; {
    const spinnerSubscription: Subscription = this.spinner$.subscribe();
    return next.handle(req).pipe(finalize(() =&gt; spinnerSubscription.unsubscribe()));
  }
}

I made an article decribing more deeply this solution : Show loader during HTTP request handeling concurrency

答案2

得分: 1

简单的实现方式:

步骤 1 - 创建自定义 HttpInterceptor 类:

import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { NgxUiLoaderService } from 'ngx-ui-loader';
import { catchError, finalize } from 'rxjs/operators';

@Injectable()
export class NgxHttpInterceptor implements HttpInterceptor {

  private count = 0;

  constructor(private ngxService: NgxUiLoaderService) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.ngxService.start();
    this.count++;
    return next.handle(req).pipe(
      catchError(error => {
        return of(error);
      }),
      finalize(() => {
        this.count--;
        if (this.count === 0) {
          this.ngxService.stop();
        }
      })
    );
  }
}

步骤 2 在你的 AppModule 中注册 CustomHttpInterceptor 类:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { CustomHttpInterceptor } from './custom-http-interceptor';

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: CustomHttpInterceptor, multi: true }
  ]
})
export class AppModule { }

在所有连续的 HTTP 请求期间,将只显示一个加载器。加载器将在第一个请求之前启动,并在最后一个响应之后停止。

英文:

The easy way to do it:

Step 1- Create a custom HttpInterceptor class:

import { Injectable } from &#39;@angular/core&#39;;
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from &#39;@angular/common/http&#39;;
import { Observable, of } from &#39;rxjs&#39;;
import { NgxUiLoaderService } from &#39;ngx-ui-loader&#39;;
import { catchError, finalize } from &#39;rxjs/operators&#39;;

@Injectable()
export class NgxHttpInterceptor implements HttpInterceptor {

  private count = 0;

  constructor(private ngxService: NgxUiLoaderService) { }

  intercept(req: HttpRequest&lt;any&gt;, next: HttpHandler): Observable&lt;HttpEvent&lt;any&gt;&gt; {
    this.ngxService.start();
    this.count++;
    return next.handle(req).pipe(
      catchError(error =&gt; {
        return of(error);
      }),
      finalize(() =&gt; {
        this.count--;
        if (this.count === 0) {
          this.ngxService.stop();
        }
      })
    );
  }
}

Step 2 Register the CustomHttpInterceptor class in your AppModule:

import { HTTP_INTERCEPTORS } from &#39;@angular/common/http&#39;;
import { NgModule } from &#39;@angular/core&#39;;
import { CustomHttpInterceptor } from &#39;./custom-http-interceptor&#39;;

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: CustomHttpInterceptor, multi: true }
  ]
})
export class AppModule { }

You will have only a single loader displayed during all continuous HTTP requests. The loader will start once before the first request and stop after the last response.

huangapple
  • 本文由 发表于 2023年2月14日 00:52:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75438911.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定