HttpClient post 未完成内部解析防护,除非通过“take(1)”进行管道传输
HttpClient post not completing inside resolve guard unless piped through `take(1)`
我有一个 Angular 带有路由和 resolve guard 的应用程序。 resolve guard 是异步的并且 returns 从 HttpClient.post
返回一个 observable - 问题是,AJAX 请求完成但 observable 没有完成,因此解析器永远不会完成它的工作,并且页面永远不会显示。但是,当我通过 take(1)
管道传输结果时,它确实完成并且工作正常。我的问题是为什么? HttpClient.post
不是应该在 AJAX 请求 returns ok (200 OK
) 之后完成吗?
这是我的解析器代码:
@Injectable()
export class MyDataResolver implements Resolve<MyData> {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
: MyData | Observable<MyData> | Promise<MyData> {
return this.svc.getData().pipe(take(1)); // <-- Why is take(1) necessary here??
}
constructor(private svc: MyService) { }
}
这里是调用post
的服务方法:
import { HttpClient } from '@angular/common/http';
export class MyService {
constructor(private http: HttpClient) {}
getData(): Observable<MyData> {
return this.http.post('/api/data'), {}).pipe(
map((resp: { data: SomeData }) => resp.data),
map(r => convertSomeDataToMyData(r)));
}
}
谢谢
我不得不回答我自己的问题,因为我找到了答案。问题出在我使用的一个拦截器,也就是这张图中的隐藏变量。
我的应用程序使用 ngrx
进行 redux 存储管理。我的拦截器点击商店以获取授权令牌。
这是我的拦截器代码:
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private store: Store<fromStore.State>,
private route: Router) { }
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpSentEvent
| HttpHeaderResponse
| HttpProgressEvent
| HttpResponse<any>
| HttpUserEvent<any>> {
const rc = this.store.select(x => x.main.token).pipe(
take(1), // <--- This is where the take(1) was needed
switchMap(r => {
const req2 = request.clone({
setHeaders: {
Authorization: `Bearer ${r}`
}
});
return next.handle(req2);
}));
return rc;
}
}
如您所见,如果没有上面的 take(1)
,拦截器修改的请求实际上永远不会完成,因为商店订阅永远不会完成。
希望这个晦涩的案例对某人有所帮助:)
我有一个 Angular 带有路由和 resolve guard 的应用程序。 resolve guard 是异步的并且 returns 从 HttpClient.post
返回一个 observable - 问题是,AJAX 请求完成但 observable 没有完成,因此解析器永远不会完成它的工作,并且页面永远不会显示。但是,当我通过 take(1)
管道传输结果时,它确实完成并且工作正常。我的问题是为什么? HttpClient.post
不是应该在 AJAX 请求 returns ok (200 OK
) 之后完成吗?
这是我的解析器代码:
@Injectable()
export class MyDataResolver implements Resolve<MyData> {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
: MyData | Observable<MyData> | Promise<MyData> {
return this.svc.getData().pipe(take(1)); // <-- Why is take(1) necessary here??
}
constructor(private svc: MyService) { }
}
这里是调用post
的服务方法:
import { HttpClient } from '@angular/common/http';
export class MyService {
constructor(private http: HttpClient) {}
getData(): Observable<MyData> {
return this.http.post('/api/data'), {}).pipe(
map((resp: { data: SomeData }) => resp.data),
map(r => convertSomeDataToMyData(r)));
}
}
谢谢
我不得不回答我自己的问题,因为我找到了答案。问题出在我使用的一个拦截器,也就是这张图中的隐藏变量。
我的应用程序使用 ngrx
进行 redux 存储管理。我的拦截器点击商店以获取授权令牌。
这是我的拦截器代码:
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private store: Store<fromStore.State>,
private route: Router) { }
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpSentEvent
| HttpHeaderResponse
| HttpProgressEvent
| HttpResponse<any>
| HttpUserEvent<any>> {
const rc = this.store.select(x => x.main.token).pipe(
take(1), // <--- This is where the take(1) was needed
switchMap(r => {
const req2 = request.clone({
setHeaders: {
Authorization: `Bearer ${r}`
}
});
return next.handle(req2);
}));
return rc;
}
}
如您所见,如果没有上面的 take(1)
,拦截器修改的请求实际上永远不会完成,因为商店订阅永远不会完成。
希望这个晦涩的案例对某人有所帮助:)