代码之家  ›  专栏  ›  技术社区  ›  Aviad P.

httpclient post未在resolve guard内完成,除非通过'take(1)'`

  •  0
  • Aviad P.  · 技术社区  · 6 年前

    我有一个带路由和解析保护的角度应用程序。解析保护是异步的,并返回从 HttpClient.post -问题是,Ajax请求完成了,但是Observable没有完成,因此解析器永远不会完成它的工作,页面也永远不会显示出来。但是当我把结果通过管道 take(1) 它确实完成了,而且工作得很好。我的问题是为什么?不是 httpclient.post网站 应该在Ajax请求返回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)));
      }
    }
    

    谢谢

    1 回复  |  直到 6 年前
        1
  •  1
  •   Aviad P.    6 年前

    因为我找到了答案,所以我不得不自己回答问题。这个问题源于我使用的拦截器,它是图片中隐藏的变量。

    我的应用程序使用 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) 在那里,拦截器修改的请求实际上从未完成,因为存储订阅从未完成。

    希望这个不起眼的案子能帮上忙:)