订阅可观察的Angular HTTP拦截器,然后返回next.handle,但抛出TypeError:您提供了'undefined' [英] Angular HTTP Interceptor subscribing to observable and then returning next.handle but throwing TypeError: You provided 'undefined'
问题描述
我有一个HTTP拦截器,在每个请求之前,我都要检查访问令牌是否过期,如果是,我从服务中订阅一个http.post调用,然后订阅它,当我得到一个新的访问令牌时,像这样调用next.handle(request):
I have a HTTP interceptor and before every request I check if the access token is expired, if it is, I subscribe to a http.post call from my service and then subscribe to it and when I get a new access token I call next.handle(request) like this:
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调用错误.
Which makes me think I'm making that http.post call wrong right there.
我还没有机会进行彻底的测试,但到目前为止看来一切正常.在返回整个地图之前,我有一个console.log,但是它没有触发,但是,其他所有方法都起作用,并且每当我获得新的访问令牌并且DID发生时,我都会在各处/权限更新currentUser,因此出于所有意图和目的似乎有效,这是更新的代码:
EDIT 1: I haven't had the chance to test this thoroughly but so far it seems that everything works. I had a console.log before returning the whole map but it didn't fire, however, everything else worked and I update the currentUser everywhere/permissions everytime I get a new access token and that DID happen, so for all intents and purposes it seems to work, here's the updated code:
mergeMap(token => {
this.auth.newAccessToken = token;
request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(request);
})
推荐答案
您不会在拦截器内subscribe()
,而是将返回Observable<HttpEvent<any>>
.这可以通过使用RxJS可管道运算符('rxjs/operators'
)来完成,例如点击 (针对设置newAccessToken
等副作用)和 switchMap 或 mergeMap 与pipe()
结合使用,返回类型为Observable<HttpEvent<any>>
的可观察值来满足 HttpInterceptor 接口:
You would not subscribe()
inside the interceptor, instead you would return an Observable<HttpEvent<any>>
. This can be done by utilizing RxJS pipeable operators ('rxjs/operators'
) such as tap (for side effects like setting newAccessToken
) and switchMap or mergeMap in combination with pipe()
, returning an observable of type Observable<HttpEvent<any>>
to satisfy the HttpInterceptor interface:
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);
})
);
}
}
这是一个示例.请检查日志以查看正在注销的关键信息.
Here is an example in action. Please check out the logs to see key information being logged out.
希望有帮助!
这篇关于订阅可观察的Angular HTTP拦截器,然后返回next.handle,但抛出TypeError:您提供了'undefined'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!