我正在按照这个教程 https:/angular-academy.comangular-jwt。 我的HTTP拦截器类需要一点帮助。
当我在401(Unauthorized error)后成功刷新token时,代码重试HTTP调用,我得到了OK,但视图和订阅没有更新,有时我得到以下错误。
core.js:9110 ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at subscribeTo (subscribeTo.js:27)
at subscribeToResult (subscribeToResult.js:11)
at CatchSubscriber.error (catchError.js:38)
at XMLHttpRequest.onLoad (http.js:1974)
at ZoneDelegate.invokeTask (zone-evergreen.js:391)
at Object.onInvokeTask (core.js:34182)
at ZoneDelegate.invokeTask (zone-evergreen.js:390)
at Zone.runTask (zone-evergreen.js:168)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:465)
at invokeTask (zone-evergreen.js:1603) (editado)
这是我的401处理程序。
private handle401Error(request: HttpRequest<any>, next: HttpHandler,tokens) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.auth.refreshToken(tokens).pipe(
switchMap((token: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(token.token);
this.db.removeAll('token');
this.db.storage.set('token',token);
return next.handle(this.addToken(request, token.token));
})).subscribe(r => r);
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
console.log(jwt)
return next.handle(this.addToken(request, jwt));
}));
}
}
所以,我们又来了。
抛出这个错误是因为你没有在你的 intercept()
方法,如果错误是 401
如果我没记错的话,你的第一个帖子)。
你不应该在拦截器中手动订阅。Angular已经为你做了。你需要使用 RxJS 运算符来返回一个可观察的对象,例如 switchMap
. 副作用使用 tap
运营商。
您的 handle401Error
删除订阅后应。
private handle401Error(request: HttpRequest<any>, next: HttpHandler,tokens) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.auth.refreshToken(tokens).pipe(
switchMap((token: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(token.token);
this.db.removeAll('token');
this.db.storage.set('token',token);
return next.handle(this.addToken(request, token.token));
}));
} else {
// I'm not sure about this part since to me it seems that in this block the
// subject it will always emit null value after the token expires and the
// browser is refreshed because the data won't persist.
// if I'm right use this here and should work: **return next.handle(request);**
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
console.log(jwt)
return next.handle(this.addToken(request, jwt));
}));
}
}
这个... intercept
方法,删除 next.handle 后的 .subscribe(r => r) 调用。
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.authService.getJwtToken()) {
request = this.addToken(request, this.authService.getJwtToken());
}
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
// here don't forget tor return
return this.handle401Error(request, next);
} else {
return throwError(error);
}
}));
}
试着在 next.handle 之后删除 .subscribe(r => r) 的调用。你需要返回observable,而不是函数调用。
return next.handle(
this.addToken(request, token.token)
);