在 Angular 2+ 中一个接一个地执行解析器
Executing resolvers one after the other in Angular 2+
给定以下路线:
path: '',
component: MyComponent,
resolve: {
foo: FooResolver,
bar: BarResolver
}
有什么方法可以告诉 angular 执行第一个解析器 FooResolver
,并且只在第一个解析器完成后才执行第二个解析器 BarResolver
?
解析器是并行解析的。如果 Foo
和 Bar
应该串联解析,它们应该是单个 FooBar
解析器。如果他们应该在其他路由中自己使用,FooBar
可以包装 Foo
和 Bar
解析器:
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
应该知道从 Foo
和 Bar
返回的承诺或可观察到的事实,以便正确解决它们。否则应添加额外的安全装置,如 await Observable.from(this.fooResolver.resolve(route)).toPromise()
.
FooBar
和 Foo
或 Bar
不应出现在同一路线中,因为这会导致重复的分辨率。
我发现了一个稍微更优雅的解决方案,如果您不关心所有解析器的结果,可以使用它:
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())
);
}
}
我用它来触发我服务中的数据加载。而且因为他们将数据/isLoading/错误写入 Akita 存储,所以我不关心解析器的结果。
我在单个 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})))
}
}
另一种选择是包装您的依赖路由并在包装器上使用必要的解析器。
I.E.
{ path: '', resolve: { foo$: FooResolver }, children: [
{ path: 'mySubRoute', resolve: {bar$: BarResolver }, component: BarComponent }
]}
*如果遇到相对路径解析问题,请尝试使用
relativeLinkResolution: "corrected"
在 forRoot 路由器方法中。更多信息在这里
给定以下路线:
path: '',
component: MyComponent,
resolve: {
foo: FooResolver,
bar: BarResolver
}
有什么方法可以告诉 angular 执行第一个解析器 FooResolver
,并且只在第一个解析器完成后才执行第二个解析器 BarResolver
?
解析器是并行解析的。如果 Foo
和 Bar
应该串联解析,它们应该是单个 FooBar
解析器。如果他们应该在其他路由中自己使用,FooBar
可以包装 Foo
和 Bar
解析器:
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
应该知道从 Foo
和 Bar
返回的承诺或可观察到的事实,以便正确解决它们。否则应添加额外的安全装置,如 await Observable.from(this.fooResolver.resolve(route)).toPromise()
.
FooBar
和 Foo
或 Bar
不应出现在同一路线中,因为这会导致重复的分辨率。
我发现了一个稍微更优雅的解决方案,如果您不关心所有解析器的结果,可以使用它:
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())
);
}
}
我用它来触发我服务中的数据加载。而且因为他们将数据/isLoading/错误写入 Akita 存储,所以我不关心解析器的结果。
我在单个 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})))
}
}
另一种选择是包装您的依赖路由并在包装器上使用必要的解析器。
I.E.
{ path: '', resolve: { foo$: FooResolver }, children: [
{ path: 'mySubRoute', resolve: {bar$: BarResolver }, component: BarComponent }
]}
*如果遇到相对路径解析问题,请尝试使用
relativeLinkResolution: "corrected"
在 forRoot 路由器方法中。更多信息在这里