Executing resolvers one after the other in Angular 2+

不羁岁月 提交于 2019-12-03 03:45:30

Resolvers are resolved in parallel. If Foo and Bar are supposed to be resolved in series they should be a single FooBar resolver. If they are supposed to be used by themselves in other routes, FooBar can wrap Foo and Bar resolvers:

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 should be aware of the fact if it is a promise or an observable that is returned from Foo and Bar in order to resolve them properly. Otherwise additional safety device should be added, like await Observable.from(this.fooResolver.resolve(route)).toPromise().

FooBar and Foo or Bar shouldn't appear within same route because this will result in duplicate resolutions.

I found a slightly more elegant solution that can be used if you don't care about the results from all of the resolvers:

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

I use this to trigger the data loading in my services. And because they write the data / isLoading / error into an Akita storage, I don't care about the results of the resolvers.

I tackled this scenario using combineLatest in a single resolver. You can do this:

@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})))
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!