我有Service从Observable类型和HttpInterceptor获取令牌,以使用它在每个http请求中注入令牌。 事情是单个请求它工作正常但如果我使用forkJoin我将不会得到任何回复。
拦截器代码
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import { AppService } from './app.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private service: AppService
) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.service.token$.pipe(
map((token: string) => {
if (token) {
const headers = req.headers.set('Authorization', `Bearer ${token}`);
console.log(`Request for url ${req.url}`);
req = req.clone({
headers: headers
});
}
return req;
}
),
switchMap(newReq => next.handle(newReq))
)
}
}
和简单的两个请求,如
getUsers() {
return this.http.get<any[]>(`https://jsonplaceholder.typicode.com/users`);
}
getPosts() {
return this.http.get<any[]>(`https://jsonplaceholder.typicode.com/posts`);
}
在组件中
// Single One will work
this.appService.getPosts().subscribe(res => console.warn(res));
// Will not work
forkJoin([this.appService.getPosts(), this.appService.getUsers()])
.subscribe(([posts, users]) => {
console.log(posts, users);
});
我重新制作了错误,例如你可以查看它 https://stackblitz.com/edit/angular-kpxvej
只有当我在拦截器中添加take(1)但它不会是我想要的东西时它才会起作用,因为我得到了一个新的代币值将不会使用它。
在其他情况下,如果令牌只是一个字符串将起作用 像那样
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = this.service.getToken();
const headers = req.headers.set('Authorization', `Bearer ${token}`);
console.log(`Request for url ${req.url}`);
req = req.clone({
headers: headers
});
return next.handle(req);
}
答案 0 :(得分:1)
据我所知,在拦截器中,如果您将令牌用作Observable和switchMap,则可能会导致一个请求取消另一个请求。
您的特定示例将变成:(getUsers触发->拦截添加令牌,getPosts触发->拦截添加令牌)-> switchMap(取消先前被拦截的请求)->实际上只有1个请求触发。
forkJoin要求完成两个可观察对象才能触发,因此您的情况是一个得到服务器响应,另一个保持沉默。
您可以使用mergeMap代替switchMap(这不会取消请求),但是最好的解决方案是在调用services函数之前使用switchMap。
此外,将令牌作为字符串而不是可观察的是合理的,因为它在会话期间很少更改,并且您可以使用set-get到localStorage来确保它是最新的。
希望有帮助。
答案 1 :(得分:0)
通过将forkjoin
添加为observable
,尝试使用以下可观察配置。
<强> service.ts 强>
getUsers(): Observable<any[]> {
return this.http.get(`https://jsonplaceholder.typicode.com/users`)
.map(res => {
return res;
});
}
getPosts(): Observable<any[]> {
return this.http.get(`https://jsonplaceholder.typicode.com/posts`);
.map(res => {
return res;
});
}
getForkJoin(): Observable<any>{
return forkJoin(
this.getUsers(),
this.getPosts()
);
}
<强> Component.ts 强>
this.appService.getForkJoin().subscribe(([users,posts]) =>{
console.log(users);
console.log(posts);
} );
答案 2 :(得分:0)
我通过将Observable的令牌转换成字符串来解决了这个问题。而我通过这样做解决了这个问题。