簡體   English   中英

Angular HTTP Interceptor 訂閱 observable 然后返回 next.handle 但拋出 TypeError: You provided 'undefined'

[英]Angular HTTP Interceptor subscribing to observable and then returning next.handle but throwing TypeError: You provided 'undefined'

我有一個 HTTP 攔截器,在每次請求之前,我檢查訪問令牌是否已過期,如果是,我從我的服務訂閱 http.post 調用,然后訂閱它,當我獲得新的訪問令牌時,我將調用下一個。像這樣處理(請求):

        this.auth.refreshAccessToken().subscribe((token: string) => {
          this.auth.newAccessToken = token;
          request = request.clone({
            setHeaders: {
              Authorization: `Bearer ${token}`
            }
          });
          return next.handle(request);
        });

問題是它拋出TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. is TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable. TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

這讓我覺得我在那里打錯了 http.post 調用。

編輯 1:我還沒有機會徹底測試這個,但到目前為止似乎一切正常。 在返回整個地圖之前我有一個 console.log 但它沒有觸發,但是,其他一切都有效,並且每次我獲得新的訪問令牌並且 DID 發生時,我都會在任何地方更新 currentUser/權限,因此出於所有意圖和目的,它似乎工作,這是更新的代碼:

          mergeMap(token => {
            this.auth.newAccessToken = token;
            request = request.clone({
              setHeaders: {
                Authorization: `Bearer ${token}`
              }
            });
            return next.handle(request);
          })

您不會在攔截器內subscribe() ,而是返回Observable<HttpEvent<any>> 這可以通過使用 RxJS 可管道操作符( 'rxjs/operators' )來完成,例如tap (用於設置newAccessTokennewAccessToken )和switchMapmergeMappipe()結合使用,返回Observable<HttpEvent<any>>類型的Observable<HttpEvent<any>>滿足HttpInterceptor接口:

import { Injectable } from '@angular/core';
import {
  HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
import { AuthService } from './auth.service';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return this.auth.refreshAccessToken().pipe(
      tap(token => this.auth.newAccessToken = token), // side effect to set token property on auth service
      switchMap(token => { // use transformation operator that maps to an Observable<T>
        const newRequest = request.clone({
          setHeaders: {
            Authorization: `Bearer ${token}`
          }
        });

        return next.handle(newRequest);
      })
    );
  }
}

這是一個實際的例子 請查看日志以查看正在注銷的關鍵信息。

希望這有幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM