Add queueing to Angular's HttpClient

后端 未结 4 619
不思量自难忘°
不思量自难忘° 2020-12-29 00:39

I have exact same requirement as mentioned in Add queueing to angulars $http service but need implementation in Angular 4.3 or 5 using the HttpInterceptor from

4条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2020-12-29 00:53

    The Answer from Ryan Teh works like a charm if you want to generalize all of your http requests in a cue, as it is a Catch All solution.

    Here I expand it with the adequate imports for Angular 8.2.4 and rxjs 6.4.0 as there will be many users looking for cut n' paste

    My apologies for the creating a new answer instead of a comment, i still don't have enough cred for that.

    queue-interceptor.service.ts

    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs';
    import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
    import { RequestQueueService } from './request-queue.service';
    
    @Injectable()
    export class QueueInterceptorService implements HttpInterceptor {
      constructor(private queueService: RequestQueueService) { }
    
      intercept(request: HttpRequest, next: HttpHandler): Observable> {
        return this.queueService.intercept(request, next);
      }
    }
    

    request-queue.service.ts

    import { Injectable } from '@angular/core';
    import { HttpRequest, HttpHandler, HttpEvent, HttpEventType } from '@angular/common/http';
    import { Observable, ReplaySubject } from 'rxjs';
    import { tap, catchError, switchMap } from 'rxjs/operators'; 
    
    @Injectable({
      providedIn: 'root'
    })
    export class RequestQueueService {
      private queue: ReplaySubject[] = [];
    
      intercept(request: HttpRequest, next: HttpHandler): Observable> {
        const requestQueueItem$ = new ReplaySubject();
        const result$ = requestQueueItem$.pipe(
          switchMap(() => next.handle(request).pipe(
            tap(req => {
              if (req.type == HttpEventType.Response) {
                this.processNextRequest();
              }
            }),
            catchError(err => {
              this.processNextRequest();
              throw err;
            })
          ))
        );
        this.queue.push(requestQueueItem$);
    
        if (this.queue.length <= 1) {
          this.dispatchRequest();
        }
    
        return result$;
      }
    
      private processNextRequest(): void {
        if (this.queue && this.queue.length > 0) {
          this.queue.shift();
        }
        this.dispatchRequest();
      }
    
      private dispatchRequest(): void {
        if (this.queue.length > 0) {
          const nextSub$ = this.queue[0];
          nextSub$.next();
          nextSub$.complete();
        }
      }
    }
    

    and app.module.ts

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { AppComponent } from './app.component';
    import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
    import { RequestQueueService } from './YOUR_SERVICES_DIRECTORY/request-queue.service';
    import { QueueInterceptorService } from './YOUR_SERVICES_DIRECTORY/queue-interceptor.service';
    
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        HttpClientModule
      ],
      providers: [
        RequestQueueService,
        { provide: HTTP_INTERCEPTORS, useClass: QueueInterceptorService, multi: true }
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

提交回复
热议问题