在Angular 2+中依次执行解析器

18

给出以下路由:

path: '',
component: MyComponent,
resolve: {
    foo: FooResolver,
    bar: BarResolver
}

有没有办法告诉Angular先执行第一个解析器FooResolver,只有在第一个解析器完成后再执行第二个解析器BarResolver


无论你想做什么,总有更好的方法。 - Carsten
这取决于 foobar 是什么以及为什么它们应该按此顺序解析。但通常可以使用 FooBarResolver 来实现,该解析器会解析出一个包含 foo 和 bar 的对象。 - Estus Flask
@estus 我正在考虑这么做,如果没有其他方法,我会这样做,但出于重用目的,我更愿意使用不同的解析器来实现。 - Ivan Aguilar
@estus 基本上 foobar 是从数据库检索出来的 JSON 对象,我不关心执行顺序,但它们必须一个接一个地执行。 - Ivan Aguilar
1
我遇到了同样的问题,但更加复杂。在我的情况下,barbaz依赖于foo,但在某些路由中,baz是可选的。最终,我创建了一个名为FooBarBaz的解析器,它处理了可选的baz。据我所知,目前没有更好的方法。 - Estus Flask
4个回答

35

解析器会并行解析。如果FooBar应该按顺序解析,它们应该成为单个FooBar解析器。如果它们应该在其他路由中单独使用,FooBar可以包装FooBar解析器:

class FooBarResolver implements Resolve<{ foo: any, bar: any }> {
  constructor(
    protected fooResolver: FooResolver,
    protected barResolver: BarResolver
  ) {}

  async resolve(route): Promise<{ foo: any, bar: any }> {
    const foo = await this.fooResolver.resolve(route);
    const bar = await this.barResolver.resolve(route);

    return { foo, bar };
  }
}

FooBar需要知道FooBar返回的是Promise还是Observable以便正确解决它们,否则需要添加额外的安全措施,例如await Observable.from(this.fooResolver.resolve(route)).toPromise()

FooBarFooBar不应出现在同一路由中,因为这会导致重复解析。


2
和任何其他解析器一样,它在路由上被指定为 resolve: { fooBar: FooBarResolver } ,并且解析后的数据可以通过 activatedRoute.data['fooBar'].foo 等方式在路由组件中使用。 - Estus Flask

1
我找到了一种更加优雅的解决方案,如果您不关心所有解析器的结果,可以使用它:
class FooBarResolver implements Resolve<Observable<any>> {
    constructor(
        protected fooResolver: FooResolver,
        protected barResolver: BarResolver
    ) { }

    resolve(): Observable<any>
    {
        return this.fooResolver.resolve().pipe(
            concat(this.barResolver.resolve()),
            concat(this.barResolver.resolve())
        );
    }
}

我使用这个来触发我的服务中的数据加载。由于它们将数据/正在加载/错误写入Akita存储中,所以我不需要关心解析器的结果。

1
另一种选择是包装您的依赖路由并在包装器上使用必要的解析器。
例如:
{ path: '', resolve: { foo$: FooResolver }, children: [
    { path: 'mySubRoute', resolve:  {bar$: BarResolver }, component: BarComponent }
]}

如果您遇到相对路径解析问题,请尝试使用

relativeLinkResolution: "corrected"

在 forRoot 路由方法中。更多信息请参见 具有空路径的组件中的 Angular RouterLink 相对路径无法正常工作


0

我使用单个resolver中的combineLatest解决了这种情况。你可以这样做:

@Injectable({providedIn: 'root'})
export class FooBarResolver implements Resolve<any> {
  constructor(
    private readonly fooResolver: FooResolver,
    private readonly barResolver: BarResolver  
  ) {}

  resolve() {
    return combineLatest(
      this.fooResolver.resolve(), 
      this.barResolver.resolve()
    ).pipe(map(([users, posts]) => ({users, posts})))
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接