1

I have tried this a bunch of ways. This method is very much by the book, however, my HTTP Interceptor is not forwarding the reportProgress events to my component. I can see the events at the Interceptor, but they are not at the component no matter what I try (eg {observe: 'events'} etc). I can't figure how to get the progress in the component.

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 Answer 1

2

You're only emitting the response event from the interceptor.

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

You should move observer.next out of the if block:

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

I would personally do this in a pipe rather than creating a new subscription, but that's irrelevant to the solution.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.