Angular Http Interceptor блокирует события http http - PullRequest
0 голосов
/ 09 марта 2020

Я пробовал это несколькими способами. Этот метод очень подходит для книги, однако мой HTTP-перехватчик не пересылает события reportProgress моему компоненту. Я вижу события на Перехватчике, но они не на компоненте, независимо от того, что я пытаюсь (например, {observe: 'events'} et c). Я не могу понять, как получить прогресс в компоненте.

interceptor.ts

import {Component, Input, OnInit} from '@angular/core';
import {
  HttpClient,
  HttpRequest,
} from '@angular/common/http';
import {tap} from 'rxjs/operators';
import {AlertService} from '../../services/alert.service';

@Component({
  selector: 'app-upload',
  templateUrl: './upload.component.html',
  styleUrls: ['./upload.component.scss']
})

export class UploadComponent implements OnInit {

  constructor(private http: HttpClient, public alertService: AlertService) {
  }

  ngOnInit(): void {
  }

  files: File[] = [];

  upload(files: File[]) {
    this.files = files;
    for (let file of files) {
      const formData: FormData = new FormData();
      formData.append('file', file, file.name);

      const url = 'http://localhost:4000/upload';

      const req = new HttpRequest('POST', url, formData, {
        reportProgress: true
      });

      this.http.request(req)
        .pipe(
          tap(console.log) // ONLY THE FINAL RESPONSE HERE
        )
        .subscribe();

    }
  }
}

component.ts

import {Injectable} from '@angular/core';
import {
  HttpResponse,
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import {Observable} from 'rxjs';
import {StateService} from '../services/state.service';

@Injectable()
export class LoaderInterceptor implements HttpInterceptor {
  private requests: HttpRequest<any>[] = [];

  constructor(private alertService: AlertService, private stateService: StateService) {
  }

  removeRequest(req: HttpRequest<any>) {
    const i = this.requests.indexOf(req);
    if (i >= 0) {
      this.requests.splice(i, 1);
    }
    this.stateService.isLoading$.next(this.requests.length > 0);
  }

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

    this.requests.push(req);
    this.stateService.isLoading$.next(true);
    return new Observable(observer => {
      const subscription = next.handle(req)
        .subscribe(
          event => {
              console.log(event); // I CAN SEE THE LOADED EVENT HERE
            if (event instanceof HttpResponse) {
              this.removeRequest(req);
              observer.next(event);
            }
          },
          err => {
            this.alertService.setAlert('error', err.message);
            this.removeRequest(req);
            observer.error(err);
          },
          () => {
            this.removeRequest(req);
            observer.complete();
          });
      // remove request from queue when cancelled
      return () => {
        this.removeRequest(req);
        subscription.unsubscribe();
      };
    });
  }
}

1 Ответ

1 голос
/ 09 марта 2020

Вы отправляете только событие ответа от перехватчика.

if (event instanceof HttpResponse) {
  this.removeRequest(req);
  observer.next(event);
}

Вы должны переместить observer.next из блока if:

const subscription = next.handle(req)
  .subscribe(event => {
    console.log(event); // I CAN SEE THE LOADED EVENT HERE
    if (event instanceof HttpResponse) {
      this.removeRequest(req);      
    }
    // MOVED HERE
    observer.next(event);
  }, err => {
    this.alertService.setAlert('error', err.message);
    this.removeRequest(req);
    observer.error(err);
  }, () => {
    this.removeRequest(req);
    observer.complete();
  });

Я бы лично сделал это в трубе, а не создавать новую подписку, но это не имеет отношения к решению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...