在定义路由时,可以通过在路由上加上一个 resolve 属性来实现路由的解析及数据预加载。但是有时候,Angular 路由解析器似乎会执行两次,这会导致性能问题。解决这个问题的方法是使用 rxjs 的操作符来处理。
假设我们有这样一个路由:
const routes: Routes = [
{
path: 'items',
component: ItemsComponent,
resolve: {
items: ItemsResolver
}
}
];
其中,ItemsResolver
是一个从远程 API 获取数据的解析器。如果路由解析器执行两次,那么在控制台中将会看到两次 ItemsResolver
的输出。
为了解决这个问题,我们可以使用 rxjs 的 shareReplay
操作符来缓存 API 的响应。如下所示:
@Injectable({
providedIn: 'root'
})
export class ItemsResolver implements Resolve {
constructor(private httpClient: HttpClient) {}
resolve() {
return this.httpClient.get('https://api.example.com/items').pipe(shareReplay());
}
}
这里使用了 shareReplay
操作符,它会把请求的响应保存在一个缓存流中,以便之后的订阅也可以共享这个缓存流中的数据。这个操作符会把已经发射过的数据缓存起来,并将缓存中的最后一个值交给新订阅者。这样就可以避免路由解析器重复执行 ItemsResolver
。