#angular #typescript #angular-httpclient #angular-http-interceptors #angular-observable
#угловой #typescript #angular-httpclient #угловые http-перехватчики #угловой-наблюдаемый
Вопрос:
У меня есть HTTP-перехватчик, и перед каждым запросом я проверяю, истек ли срок действия токена доступа, если это так, я подписываюсь на вызов http.post из моей службы, а затем подписываюсь на него, и когда я получаю новый токен доступа, я вызываю next.handle (запрос) следующим образом:
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.
Что заставляет меня думать, что я делаю этот вызов http.post неправильно прямо здесь.
РЕДАКТИРОВАТЬ 1: у меня не было возможности тщательно протестировать это, но пока кажется, что все работает. У меня была консоль.войдите в систему перед возвратом всей карты, но она не сработала, однако все остальное работало, и я обновляю CurrentUser везде / разрешения каждый раз, когда получаю новый токен доступа, и это произошло, так что для всех целей и целей это, похоже, работает, вот обновленный код:
mergeMap(token => {
this.auth.newAccessToken = token;
request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(request);
})
Комментарии:
1. Попробуйте добавить
return
перед вызовом refreshAccessToken, например:return this.auth.refreshAccessToken...
2. Вы не можете использовать subscribe здесь. Вместо этого вам нужно вернуть наблюдаемое с помощью pipe () и оператора RxJS, такого как map() или switchMap()
3. @AlexanderStaroselsky В итоге я сделал это с помощью mergeMap, и я обновил свой код, кажется, все работает, если вы хотите опубликовать его в качестве ответа, я с радостью отмечу его как правильный. В итоге я поставил return перед всем этим, но я попробовал это перед использованием mergemap, и компилятор закричал на меня, поэтому я бы сказал, что карта слияния была def. полезный / правильный ответ, извините @artsnr!
Ответ №1:
Вы не subscribe()
были бы внутри перехватчика, вместо этого вы бы вернули an Observable<HttpEvent<any>>
. Это можно сделать, используя RxJS pipeable operators ( 'rxjs/operators'
), такие как tap (для побочных эффектов, таких как настройка newAccessToken
) и switchMap или mergeMap в сочетании с pipe()
, возвращая наблюдаемый тип 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);
})
);
}
}
Вот пример в действии. Пожалуйста, просмотрите журналы, чтобы увидеть, как ключевая информация выходит из системы.
Надеюсь, это поможет!