除非通过 `take(1)` 进行管道传输,否则 HttpClient 帖子无法在解析防护内完成

Avi*_* P. 1 angular-routing angular angular-httpclient angular6

我有一个带有路由和解析防护的 Angular 应用程序。解析守卫是异步的,并返回一个从返回的可观察量HttpClient.post- 问题是,AJAX 请求完成但可观察量没有完成,因此解析器永远不会完成其工作,并且页面永远不会显示。然而,当我通过管道传输结果时,take(1)它确实完成并且工作正常。我的问题是为什么?HttpClient.postAJAX 请求返回 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) { }

}
Run Code Online (Sandbox Code Playgroud)

这是调用的服务方法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)));
  }
}
Run Code Online (Sandbox Code Playgroud)

谢谢

Avi*_* P. 5

我被迫回答我自己的问题,因为我已经找到了答案。问题源于我使用的一个拦截器,也就是这张图中的隐藏变量。

我的应用程序用于ngrxredux 存储管理。我的拦截器点击商店来获取授权令牌。

这是我的拦截器代码:

@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;
  }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,如果没有take(1)那里,拦截器修改的请求实际上永远不会完成,因为商店订阅永远不会完成。

希望这个不起眼的案例对某人有所帮助:)