【问题标题】:Angular 6 | Only call a resolver once角 6 |只调用一次解析器
【发布时间】:2018-12-31 05:59:45
【问题描述】:

我的一条路线上有一个解析器,以便让它在页面实际加载之前获取数据。这需要多个请求,因此我使用rxjs 函数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();

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

this.activatedRoute.data.subscribe((data) => {
   this.author = data[0][0];
   this.comments = data[0][1].data;
});

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

提前致谢。

【问题讨论】:

  • 我看到了两个选项:通过拦截器 + 缓存服务(参见 angular.io/guide/http#caching)在 HttpClient 级别缓存,或者创建一个专门的有状态服务来跟踪用于请求的最后一个参数 + 请求响应。每当解析器尝试获取时,逻辑应该检查服务并确认新参数是否与先前存储的参数匹配,在这种情况下可以使用缓存的响应。
  • 我从没想过最后一个选项。你个人认为最好的是什么?
  • 但是,我认为第二个选项不会起作用,因为没有办法存储它所拥有的第一个选项以检查当前选项?
  • 第二,http缓存主要用于在处理新请求期间重放响应。不是为了避免新的请求。
  • 用 ReplaySubject 缓存它

标签: angular routes rxjs resolver


【解决方案1】:

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

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

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

}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 2013-06-02
    • 1970-01-01
    相关资源
    最近更新 更多