【问题标题】:Executing resolvers one after the other in Angular 2+在Angular 2+中一个接一个地执行解析器
【发布时间】:2020-05-11 21:25:55
【问题描述】:

给定以下路线:

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

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

【问题讨论】:

  • 无论你想做什么。有更好的方法。
  • 这取决于foobar 是什么以及为什么要按此顺序解决它们。但通常这可以通过 FooBarResolver 来实现,它解析为包含 foo 和 bar 的对象。
  • @estus 我正在考虑这样做,如果没有其他方法我会这样做,但我更愿意使用不同的解析器来实现重用。
  • @estus 基本上foobar 是从数据库中检索的json 对象,我不关心执行顺序,但它们必须一个接一个地执行。
  • 我有同样的问题,但更复杂。在我的情况下,barbaz 依赖于 foobaz 在某些路由中是可选的。最终我得到了FooBarBaz 解析器,它负责处理可选的 Baz。据我所知,目前没有更好的方法。

标签: angular angular2-routing


【解决方案1】:

解析器是并行解析的。如果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 不应出现在同一路由中,因为这会导致重复解析。

【讨论】:

  • @DanyGauthier 与任何其他解析器一样,它在路由上指定为resolve: { fooBar: FooBarResolver },解析后的数据在路由组件中以activatedRoute.data['fooBar'].foo 等形式提供。
【解决方案2】:

如果您不关心所有解析器的结果,我发现了一个稍微更优雅的解决方案:

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())
        );
    }
}

我使用它来触发我的服务中的数据加载。而且因为他们将 data / isLoading / error 写入 Akita 存储,所以我不关心解析器的结果。

【讨论】:

    【解决方案3】:

    我在单个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})))
      }
    }
    

    【讨论】:

      【解决方案4】:

      另一种选择是包装您的依赖路由并在包装器上使用必要的解析器。

      I.E.

      { path: '', resolve: { foo$: FooResolver }, children: [
          { path: 'mySubRoute', resolve:  {bar$: BarResolver }, component: BarComponent }
      ]}
      

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

      relativeLinkResolution: "corrected"
      

      在forRoot路由器方法中。更多信息在这里Angular RouterLink relative path does not work in component having empty path

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多