[英]Angular - How to add an access token from an observable to an outgoing HTTP request?
在我的UserService
我有一个用户Observable
对象,它保存登录用户的UserModel
。对于测试,我在ngOnInit()
内部实现了登录过程:
this.userService.authenticate('###', '###')
.subscribe(res => console.log('authenticated'));
private userSource = new BehaviorSubject<UserModel>(null);
public user = this.userSource.asObservable();
我的UserModel提供了一个名为authKey的属性,用于API身份验证。
在我的ProjectService
我想做一个api请求; 为此,需要存储在UserModel
的api密钥。 可以只订阅用户属性,但我读到了避免在服务中进行订阅。
题
如何将此订阅与管道/映射相关联? 我的方法是以下代码; 但这感觉就像糟糕的代码。
suggest(term: string): Observable<ProjectModel[]> {
return this.userSrv.user.pipe(
mergeMap((user: UserModel) => {
const options = {params: {'access-token': user.accessToken}};
return this.http.get<ProjectModel[]>(this.conf.url, options).pipe(
map(response => {
// mapping the projects ...
return projects;
})
);
})
);
}
您应该使用HttpInterceptor: https ://angular.io/api/common/http/HttpInterceptor,而不是传递每个请求的访问令牌。 它将为您执行的每个http请求添加AccessToken。 将用户存储在UserService中的BehaviorSubject中,并在Interceptor中使用它。
在此之后,您的功能将如下所示:
suggest(term: string): Observable<ProjectModel[]> {
return this.http.get<ProjectModel[]>(this.conf.url + '/my-endpoint');
}
正如前面的答案中所述, HTTP拦截器最适合您的用例。
基本想法如下:
import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
import {mergeMap,map} from 'rxjs/operators';
import {Observable} from 'rxjs';
function isLoginRequest(req: HttpRequest<any>): boolean {
// implement
}
@Injectable()
export class AccessTokenInterceptor implements HttpInterceptor {
constructor(private readonly userService: UserService){}
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
if(isLoginRequest(req)) return next.handle(req);
return this.userService.user.pipe(
map(user => req.clone({setParams:{'access-token': user.accessToken}})),
mergeMap(req => next.handle(req))
);
}
}
别忘了注册这个拦截器,如文档中所示。
通过使用此功能,您的原始服务功能将减少为:
suggest(term: string): Observable<ProjectModel[]> {
return this.http.get<ProjectModel[]>(this.conf.url).pipe(
map(response => {
// mapping the projects ...
})
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.