角 6 | 只调用一次解析器

2 routes resolver rxjs angular

我的其中一个路由上有一个解析器,以允许它在页面实际加载之前获取数据。这需要多个请求,因此我使用的是rxjsfunction forkJoin。这将返回大量数据,并且在所有数据完全加载之前页面不会加载,这正是我想要的。

但是,获取的数据非常庞大,这意味着在路由加载之前可能需要一段时间。我想以某种方式,仍然解析这条路线,然后缓存它并让组件知道这是缓存的。

我依赖从activatedRoute组件内部返回的数据,因为页面需要它。所以我需要它停止覆盖当前存在的内容。

到目前为止,这是我的代码:

解析器:

const postId: string = this.postService.data.post.id;

const authorData$: Observable<HttpResponse<any>> = this.authorService.getAuthor();
const commentsData$: Observable<HttpResponse<any>> = this.commentsService.getComments();
Run Code Online (Sandbox Code Playgroud)

我知道这可以在一个请求中完成,但这只是我将使用它的一个例子。所以我不想要一个说把它放在一个请求中的建议。

this.activatedRoute.data.subscribe((data) => {
   this.author = data[0][0];
   this.comments = data[0][1].data;
});
Run Code Online (Sandbox Code Playgroud)

所以我只想在组件的第一次加载时执行此操作。

提前致谢。

tom*_*een 6

这样做的一种方法是在解析器中引入一个重放主题,它将充当缓存。解析器将始终返回此主题,但它只会请求数据,如果它尚未请求任何数据。

我做了一个简单的例子,其中解析器只需要返回一个数字,它从一个简单的数据服务中获取。

class Resolver implements Resolve<number> {
    // We need to keep track on if a request has already been sent
    requested = false;
    // The replay subject will emit the last value that has been passed in
    subject = new ReplaySubject<number>(1);

    resolve(route: ActivatedRouteSnapshot): Observable {
        // Request data only if it has not been requested yet
        if (!this.requested) {
            this.requested = true;
            
            // Do your heavy call here
            this.service.getData()
                // Emit your data into the subject
                .subscribe(nr => this.subject.next(nr));
        }

        // Return the subject. Pipe in first() because resolvers 
        // only emit on completion of an observable.
        return this.subject.pipe(first());
    }

}
Run Code Online (Sandbox Code Playgroud)

你也应该能够做到这一点。如果您有多个调用,您可以使用 forkJoin 或类似方法来执行两个调用并将结果提供给重放主题。或者您可以创建两个单独的解析器,每个解析器只负责一个结果对象。