【问题标题】:Angular HttpClient observable not completingAngular HttpClient observable 未完成
【发布时间】:2019-06-05 10:30:34
【问题描述】:

我有以下代码:

// in a service
downloadCSV(): Observable<Blob> {
  return this.httpClient.get(`${apiUrl}/a.csv`, {responseType: 'blob'});
}
// in component
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('completed!');
      }
    );
}

数据已正确记录但“已完成!”不会被记录,并且永远不会调用 finalize。

编辑:

所以经过进一步调查,问题似乎与添加了身份验证标头的拦截器有关。

如果拦截器被绕过(并且在服务器上禁用了身份验证),则 observable 完成且没有错误。

我不明白为什么会这样。可能与请求被克隆的事实有关?

//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.com') === 0) {
    scope = 'https://graph.microsoft.com';
  }
  else if (req.url.indexOf('https://management.azure.com') === 0) {
    scope = 'https://management.azure.com';
  }
  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);
  }
}

【问题讨论】:

  • 无法在本地复制 - 我看到在使用 { responseType: 'blob' }finalizepipe 中创建 HttpClient#get 时调用了已完成的回调。
  • 按 F12 并告诉我们网络上有什么。您对此有何回应?
  • 我试图创建一个堆栈闪电战。使用了所有库的相同版本,但我也无法复制它。它只适用于某人:stackblitz.com/edit/…
  • @JohnPeters 网络选项卡看起来正常,请求在那里,代码为 200,内容看起来很好。

标签: javascript angular rxjs observable angular-httpclient


【解决方案1】:

所以问题出在我的身份验证服务的 getToken 函数中。我在归还令牌后忘记完成 observable!由于 httpClient.get observable 是通过我的 getToken observable 进行开关映射的,因此导致我在 onDownloadClicked 中的订阅永远不会完成。

// 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.complete(); // this was missing
      }
      else {
        this.login();
      }
    });
  });
}

【讨论】:

    猜你喜欢
    • 2019-06-03
    • 2020-11-05
    • 2018-09-18
    • 2018-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多