Add queueing to Angular's HttpClient

后端 未结 4 617
不思量自难忘°
不思量自难忘° 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 01:15

    I have the exact same requirement as you. The other answers work perfectly fine, just that it requires developer to create requests with another a custom service instead of native HttpClient. You could try the following interceptor to apply queuing as well.

    This solution requires you to add 2 services, a HttpInterceptor and a service (RequestQueueService) to manage the queue.

    HttpInterceptor:

    @Injectable()
    export class QueueInterceptorService implements HttpInterceptor {
      constructor(private queueService: RequestQueueService) { }
    
      intercept(request: HttpRequest, next: HttpHandler): Observable> {
        return this.queueService.intercept(request, next);
      }
    }
    

    RequestQueueService:

    @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();
        }
      }
    }
    

    Lastly, in AppModule:

    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        HttpClientModule
      ],
      providers: [
        RequestQueueService,
        { provide: HTTP_INTERCEPTORS, useClass: QueueInterceptorService, multi: true }
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    BTW, I am using Angular 8 with rxjs 6.4.

提交回复
热议问题