typescript Angular 8:如何同步Angular 解析

oo7oh9g9  于 2023-01-27  发布在  TypeScript
关注(0)|答案(2)|浏览(135)

早上好,我的问题有点复杂;
我们已进入***app.module.ts***,尤其是***RouterModule***区域:

RouterModule.forRoot([
  {path: 'xxx/:xxx', component: XxxComponent},
  {path: '', redirectTo: 'homepage', pathMatch: 'full'},
  {path: 'homepage', component: HomepageComponent, resolve: {
      answerCallHttp1: CallHttp1Resolve,
      answerCallHttp2: CallHttp2Resolve,
      answerCallHttp3: CallHttp3Resolve
    }},
  {path: 'error', component: ErrorComponent}
])

现在我的问题是:
假定answerCallHttp1answerCallHttp2answerCallHttp3具有不同的响应时间(例如,answerCallHttp1的响应时间比answerCallHttp2快得多)如何运行所有answerCallHttp*,然后在运行所有answerCallHttp*之后,我可以加载Homepage组件吗?
我如何告诉代码:加载“HomepageComponent”后先完成所有解析?
我尝试使用一个用户推荐的方法,但是它生成了一个Http调用的无限循环:

resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any> | Promise<any> | any {
    return forkJoin({
      auth: this.memory.isToken(),
      userInfo: this.foo.get(this.api + '/getUserInformation', {headers: new HttpHeaders({'Auth': this.memory.getToken()})}).subscribe(),
      retailers: this.foo.get(this.api + '/retailer', {headers: new HttpHeaders({'Auth': this.memory.getToken()}),params: new HttpParams().set('system_device', 'desktop').set('system_platform', this.getBrowserName())}).subscribe()
    });
  }

这是全部解决

调用Http1Resolve.ts

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {return this.memory.isToken();}

调用Http2Resolve.ts

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {this.foo.get(this.api + '/getUserInformation', {headers: new HttpHeaders({'Auth': this.memory.getToken()})}).subscribe(userInfo => {return userInfo;});}

调用Http 3解析. ts

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {this.foo.get(this.api + '/retailer', {headers: new HttpHeaders({'Auth': this.memory.getToken()}), params: new HttpParams().set('system_device', 'desktop').set('system_platform', this.getBrowserName())}).subscribe(retailer => {return retailer;});}
fxnxkyjh

fxnxkyjh1#

你把它从盒子里拿出来:仅在完成所有解析器之后才构建视图。
您可以通过在组件的ngOnInit和解析器本身中放入一些console.log语句来验证它(例如:return this.httpClient.get(/* ... */).pipe(tap(() => console.log('Request completed')))。

zujrkrfu

zujrkrfu2#

您可能只有一个解析器,所有HTTP调用都从它发出:

export class CombinedResolverService implements Resolve<{[key: string]: any}> {
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
    : Observable<{[key: string]: any}> {
    return forkJoin({
        answerCallHttp1: this.http.get(...), // URL 1
        answerCallHttp2: this.http.get(...), // URL 2
        answerCallHttp3: this.http.get(...), // URL 3
      });
  }
}

上述方法仅适用于rxjs版本〉= 6.5的情况。如果您使用的是以前的版本,则必须执行以下操作:

export class CombinedResolverService implements Resolve<{[key: string]: any}> {
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
    : Observable<{[key: string]: any}> {
    return forkJoin(
        this.http.get(...), // URL 1
        this.http.get(...), // URL 2
        this.http.get(...), // URL 3
      ).pipe(
        map(([answerCallHttp1, answerCallHttp2, answerCallHttp3]) => ({
            answerCallHttp1, answerCallHttp2, answerCallHttp3
          }))
      );
  }
}

我建议进行以下更改:

调用1HttpResolve.ts

由于isToken() * 不是 * 可观察的,我们将用of运算符把它变成可观察的(上面的forkJoin要求它返回可观察的):

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
  : Observable<any> | Promise<any> | any {
  return of(this.memory.isToken());
}

调用2HttpResolve.ts

您必须在此处返回观察值:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
  : Observable<any> | Promise<any> | any {
  return this.foo.get(this.api + '/getUserInformation', 
    {headers: new HttpHeaders({'Auth': this.memory.getToken()})});
}

调用3HttpResolve.ts

您必须在此处返回观察值:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
  : Observable<any> | Promise<any> | any {
  return this.foo.get(this.api + '/retailer', {
    headers: new HttpHeaders({'Auth': this.memory.getToken()}), 
    params: new HttpParams()
        .set('system_device', 'desktop')
        .set('system_platform', this.getBrowserName())
    });
}

最后,在组件中:

ngOnInit() {
  this.route.data
    .subscribe(({answerCallHttp1, answerCallHttp2, answerCallHttp3}) => {
      // do whatever you want with the data
    });
}

**[最终评论]:**顺便说一句,@mbojko在另一个答案中有一个很好的观察。我检查了他的建议,它很有效(我学到了一个新特性,太棒了!),所以你只需要在call2HttpResolve.tscall3HttpResolve.ts中做建议的修改。这是最省力的路径,同样有效。

您可以看到它在Stackblitz demo中工作。

相关问题