admin管理员组

文章数量:1357312

I have the following code:

// in a service
downloadCSV(): Observable<Blob> {
  return this.httpClient.get(`${apiUrl}/a.csv`, {responseType: 'blob'});
}
// in ponent
onDownloadClicked(event: MouseEvent) {
  this.downloading = true;
  this.service.downloadCSV()
    .pipe(finalize(() => this.downloading = false))
    .subscribe(
      (data: Blob) => {
        console.log(data);
      },
      (error) => {
        console.error(error);
        alert('Sorry, something wet wrong. Try again.');
      },
      () => {
        console.log('pleted!');
      }
    );
}

The data is logged correctly but 'pleted!' is not logged and finalize is never called.

Edit:

So on further investigation, it seems the issue is related to an interceptor which adds an auth header.

If the interceptor is bypassed (and auth disabled on the server) the observable pletes without error.

I don't understand why this is happening though. Possibly something related to the fact the request is cloned?

//interceptor code
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  let scope: string;
  // only inject tokens for the following scopes
  if (req.url.indexOf('') === 0) {
    scope = '';
  }
  else if (req.url.indexOf('') === 0) {
    scope = '';
  }
  else if (req.url.indexOf(environment.apiUrl) === 0) {
    scope = environment.appId;
  }
  if (scope) {
    return this.authService.getToken(scope).pipe(
      switchMap((token) => {
        let newReq;
        if (token) {
          const JWT = `Bearer ${token}`;
          newReq = req.clone({
            setHeaders: {
              Authorization: JWT,
            }
          });
        }
        return next.handle(newReq || req);
      })
    );
  }
  else {
    return next.handle(req);
  }
}

I have the following code:

// in a service
downloadCSV(): Observable<Blob> {
  return this.httpClient.get(`${apiUrl}/a.csv`, {responseType: 'blob'});
}
// in ponent
onDownloadClicked(event: MouseEvent) {
  this.downloading = true;
  this.service.downloadCSV()
    .pipe(finalize(() => this.downloading = false))
    .subscribe(
      (data: Blob) => {
        console.log(data);
      },
      (error) => {
        console.error(error);
        alert('Sorry, something wet wrong. Try again.');
      },
      () => {
        console.log('pleted!');
      }
    );
}

The data is logged correctly but 'pleted!' is not logged and finalize is never called.

Edit:

So on further investigation, it seems the issue is related to an interceptor which adds an auth header.

If the interceptor is bypassed (and auth disabled on the server) the observable pletes without error.

I don't understand why this is happening though. Possibly something related to the fact the request is cloned?

//interceptor code
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  let scope: string;
  // only inject tokens for the following scopes
  if (req.url.indexOf('https://graph.microsoft.') === 0) {
    scope = 'https://graph.microsoft.';
  }
  else if (req.url.indexOf('https://management.azure.') === 0) {
    scope = 'https://management.azure.';
  }
  else if (req.url.indexOf(environment.apiUrl) === 0) {
    scope = environment.appId;
  }
  if (scope) {
    return this.authService.getToken(scope).pipe(
      switchMap((token) => {
        let newReq;
        if (token) {
          const JWT = `Bearer ${token}`;
          newReq = req.clone({
            setHeaders: {
              Authorization: JWT,
            }
          });
        }
        return next.handle(newReq || req);
      })
    );
  }
  else {
    return next.handle(req);
  }
}
Share Improve this question edited Jun 5, 2019 at 14:05 mfa asked Jun 5, 2019 at 10:30 mfamfa 7097 silver badges20 bronze badges 4
  • 2 Could not replicate locally - I see the pleted callback get invoked when making an HttpClient#get with { responseType: 'blob' } and a finalize in the pipe. – jonrsharpe Commented Jun 5, 2019 at 10:38
  • Press F12 and tell us what's on network. What do you see in response? – JWP Commented Jun 5, 2019 at 11:02
  • 1 I tried to create a stackblitz. Used the same versions of all the libraries but I can't replicate it either. It just works in the sb: stackblitz./edit/… – mfa Commented Jun 5, 2019 at 11:42
  • @JohnPeters network tab looks normal, the request is in there with a code of 200 and the content looks fine. – mfa Commented Jun 5, 2019 at 11:45
Add a ment  | 

1 Answer 1

Reset to default 10

So it turns out the problem was in the getToken function of my auth service. I had forgotten to plete the observable after returning the token! Since the httpClient.get observable is switch mapped through my getToken observable it was causing my subscription in onDownloadClicked to never plete.

// from my auth service
getToken(resource: string): Observable<string> {
  return Observable.create((observer: Observer<string>) => {
    this.context.acquireToken(resource, (error, token) => {
      if (token) {
        observer.next(token);
        observer.plete(); // this was missing
      }
      else {
        this.login();
      }
    });
  });
}

本文标签: javascriptAngular HttpClient observable not completingStack Overflow