【发布时间】:2016-07-31 16:04:56
【问题描述】:
我有一个 Angular 2 应用程序,它调用 JSON API 将数据加载到嵌套的 HTML 列表 (<ol>)。本质上是一个动态生成的树视图。由于来自 API 的数据集最终会变得非常大,因此当用户打开一个分支时,树会逐渐填充(用户打开一个分支,使用已打开的节点的 id 调用 API,API 返回一个 JSON节点的直接子节点的提要,Angular 将返回的 JSON 绑定到一些新的 HTML <li> 元素并且树展开以显示新分支)。
您可以在Plunkr 中看到它的实际应用。它使用递归指令并且运行良好。 目前,因为我无法针对公共请求打开实际的 API,它只是调用静态 JSON 提要,因此每个节点的返回数据只是重复,但希望你能明白。
我现在要解决的问题是防止分支关闭然后重新打开时出现无关的 HTTP 调用。在阅读了HTTP client docs 之后,我希望这就像修改订阅数据服务的方法以将.distinctUntilChanged() 方法链接到app/content-list.component.ts 文件一样简单,如下所示:
getContentNodes() {
this._contentService.getContentNodes(this._startNodeId)
.distinctUntilChanged()
.subscribe(
contentNodes => this.contentNodes = contentNodes,
error => this.errorMessage = <any>error
);
}
但是,当我打开浏览器网络检查器时,每次重新打开相同的树分支时,它仍然会调用 API。
谁能建议如何解决这个问题?
非常感谢。
编辑:
我正在尝试在下面实现@Thierry Templier 的回答;缓存 API 返回的数据。所以内容服务现在是:
import {Injectable} from 'angular2/core';
import {Http, Response} from 'angular2/http';
import {Headers, RequestOptions} from 'angular2/http';
import {ContentNode} from './content-node';
import {Observable} from 'rxjs/Observable';
@Injectable()
export class ContentService {
constructor (private http: Http) {}
private _contentNodesUrl = 'app/content.json';
_cachedData: ContentNode[];
getContentNodes (parentId:number) {
if (this._cachedData) {
return Observable.of(this._cachedData);
} else {
return this.http.get(this._contentNodesUrl + parentId)
.map(res => <ContentNode[]> res.json())
.do(
(data) => {
this._cachedData = data;
})
.catch(this.handleError);
}
}
private handleError (error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
但是,这里发生的情况是,当页面加载时,this._cachedData 返回 false,API 调用正在触发并使用返回值 (data) 填充 this._cachedData,这是正确的。但是,当在网页 UI 中打开树节点时,以下行会重复运行数千次,直到最终浏览器崩溃:
return Observable.of(this._cachedData);
对于 Angular 2,我仍然处于起步阶段,因此非常感谢任何关于为什么这对我的学习没有帮助的指示。
【问题讨论】: