angular - 在 Angular 2 API 驱动的 TreeView 中防止重复的 HTTP 请求

标签 angular angular2-services

我有一个 Angular 2 应用程序,它调用 JSON API 将数据加载到嵌套的 HTML 列表 ( <ol> ) 中。本质上是一个动态生成的 TreeView 。由于来自 API 的数据集最终会变得非常大,当用户打开一个分支时,树会逐渐填充(用户打开一个分支,使用已打开的节点的 ID 调用 API,API 返回一个 JSON than 节点的直接子节点的提要,Angular 将返回的 JSON 绑定(bind)到一些新的 HTML <li> 元素并且树展开以显示新分支)。

您可以在这个 Plunkr 中看到它的实际效果.它使用递归指令并且运行良好。 目前,因为我无法针对公共(public)请求开放实际 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 调用正在触发和填充 this._cachedData返回值 ( data ),这是正确的。但是,当在网页 UI 中打开树节点时,以下行将重复运行数千次,直到最终浏览器崩溃:

return Observable.of(this._cachedData);

就 Angular 2 而言,我仍处于起步阶段,因此非常感谢任何关于为什么这对我的学习没有帮助的指示。

最佳答案

我将使用以下方法缓存每个节点的数据:

getData() {
  if (this.cachedData) {
    return Observable.of(this.cachedData);
  } else {
    return this.http.get(...)
          .map(res => res.json())
          .do((data) => {
            this.cachedData = data;
          });
  }
}

distinctUntilChanged 的“问题”是您需要使用相同的数据流。但你的情况并非如此,因为你对不同的数据流执行了多个请求......

有关详细信息,请参阅此问题:

关于angular - 在 Angular 2 API 驱动的 TreeView 中防止重复的 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36532684/

相关文章:

angular - 为什么我在 Angular 2 中加载 rxjs-extensions 时出错?

javascript - 服务未正确注入(inject)且页面未显示任何结果 + angular 2

javascript - Angular 2 - 使用 TypeScript 使用地理定位获取当前位置的名称

javascript - Angular 6 - 检查后表达式已更改,构建模式

angular - 单击angular2中的按钮将组件添加到dom

javascript - 从 array.splice 返回 void

angular - 在获取请求 Angular 2 上设置 header

http - 我在哪里可以进行模拟 http 调用来学习 Angular2 前端 http 调用

angularjs - DomSanitizationService 不是函数

html - 数据表寻呼机的下一个按钮和后退按钮不起作用