【问题标题】:Angular2 : Reduce number of Http callsAngular2:减少 Http 调用次数
【发布时间】:2016-09-06 09:12:57
【问题描述】:

我将 Angular2 RC5 与 ASP.NET Core 服务器一起使用,该服务器通过 API 调用来获取我的数据。 我实际上想知道是否有一种方法可以减少您使用 Angular2 进行的 http 调用次数,因为我担心如果我继续以我的方式使用组件会出现很多情况。这是一个具体的例子。

我想从数据库中获取一个由 ID 和语言定义的文本值。然后我制作了以下组件:

dico.component.ts

@Component({
    selector: 'dico',
    template: `{{text}}`,
    providers: [EntitiesService]
})

class Dico implements AfterViewInit {
    @Input() private id: string;   
    @Input() private lang: string;
    private text: string = null;

    // DI for my service
    constructor(private entitiesService: EntitiesService) {
    }

    ngAfterViewInit() {
        this.getDico();
    }

    // Call the service that makes the http call to my ASP Controller
    getDico() {
        this.entitiesService.getDico(this.id, this.lang)
            .subscribe(
            DicoText => this.text = DicoText
            );
    }
}

@Component({
    template: `<dico [id] [lang]></dico>`,
    directives: [Dico]
})

export class DicoComponent {
}

这是我的服务中的代码:

entities.service.ts

getDico(aDicoID: string, aLangue: string) {
        // Parameters to use in my controller
        let params = new URLSearchParams();
        params.set("aDicoID", aDicoID);
        params.set("aLangue", aLangue);
        // Setting up the Http request
        let lHttpRequestBody = params.toString();
        let lControllerAction: string = "/libelle";
        let lControllerFullURL: string = this.controllerURL + lControllerAction;
        let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
        let options = new RequestOptions({ headers: headers });

        return this.http.post(lControllerFullURL, lHttpRequestBody, options)
            .map((res: any) => {
                // Parsing the data from the response
                let data = res.json();

                // Managing the error cases
                switch (data.status) {
                    case "success":
                        let l_cRet: string = data.results;
                        if (l_cRet != null && !l_cRet.includes("UNDEFINED")) {
                            return data.results;
                        } else {
                            throw new Error("Erreur récupération Dico : " + l_cRet);
                        }
                    case "error":
                        throw new Error("Erreur récupération Dico : " + data.message);
                }
            }
            ).catch(this.handleError);
}

然后我可以在我的应用程序中使用我新制作的组件:

randomFile.html

<dico id="201124" lang="it"></dico>
<dico id="201125" lang="en"></dico>
<dico id="201126" lang="fr"></dico>

但是这个应用程序最终会使用数百个这样的“dico”,我想知道如何在应用程序完全加载之前管理一些预取或类似的东西。这有关系吗?从长远来看,这会影响性能吗?

任何建议将不胜感激。

EDIT :这些 dico 允许我从数据库中获取翻译成我想要的语言的文本。在这里,在上面的示例中,我有 3 个“dico”,它将以意大利语、法语和英语输出一些文本。 我的应用程序会使用很多,因为每个菜单中的每个文本都是“dico”,问题是它们会有很多,现在对于我制作的每个“dico”,我的服务都被调用并进行一次 http 调用以获取数据。我想要以某种方式定义我所有的 dicos,调用该服务,它将为我提供数组中所有 dicos 的文本以避免进行多次调用(但我真的不知道该怎么做)。

【问题讨论】:

  • 我对 Observables 还很陌生,我想这个链接很有趣,但我需要更深入地了解......不过有一个小问题,有没有办法喜欢声明我在代码中显示的“Dico”列表并告诉我的服务进行一次调用,该调用将返回我的结果数组?我真的不知道如何根据不同来映射我的结​​果...谢谢,缓存结果将是我真正需要做的事情。
  • 我认为链接答案中的答案(至少是我的)就是这样做的。无论对服务进行多少次调用,所有调用者都将保持“等待”状态,直到响应到达,然后每个调用者将立即收到完整的结果。当您可能获得更新的结果而不是缓存的结果时,它还会在后续调用中返回相同的结果。您需要告诉服务不要使用缓存。这在我的回答中没有实现,但应该很简单 - 只需添加一个清除缓存的方法,以便服务创建一个新调用。
  • 如果我理解正确的话,这个链接在你必须从多个组件中获取相同数据的情况下很有用,这样你只需要调用一次,你甚至可以缓存它以避免更多来电。在这里,我知道我将有很多 调用,因此有很多调用要做。问题是,即使我缓存它们,第一次加载也会进行数百个 http 调用......我真正想做的是像我在代码示例中所做的那样声明我的 Dicos,并告诉我的服务做一个调用将返回一个包含所有结果的数组,这样我只需为每个组件调用一次。
  • 您可以只收集来自&lt;dico&gt;s 的请求并延迟对服务器的调用,直到您全部收集完毕,然后立即请求所有需要的文本,然后回复@987654326 @s.

标签: performance angular angular2-http


【解决方案1】:

一种未经测试的基本方法(我自己不太了解可观察对象)

class DicoService {
  private subjects = {}
  private ids = [];

  getDico(String id):Observable<Dico> {
    var s = this.subjects[id];

    if(!s) {
      this.ids.push(id);
      s = new Subject(); 
      this.subjects[id]=s;
    }
    return s.asObservable().share().first();
  }

  sendRequest() {
    http.get(....) /* pass this.ids */
    map(response => response.json())
    .subscribe(data => {
      for(item in data) { // don't know how to iterate exactly because I don't know how the response will look like
        this.subject[item.id].next(item.langText);
      }
      // you might cache them if other components added by the router also request them
      // this.subjects = {};
      // this.ids = []
    });
  }  
}
<dico [text]="dicoService.getDico('someId') | async"></dico>
ngAfterViewInit() {
  this.dicoService.sendRequest();
}

【讨论】:

  • 很好,我会尽快做类似的事情。不过有一个问题,.take(1); 是做什么的?谢谢
  • 这使得 observable 在收到订阅者的一个值后关闭。如果您想继续向订阅者发送更新,请忽略 .take(1)
  • 另一件事我不明白:this.subjects[id]=o;:那里是什么?对不起,如果这看起来很明显......
  • 对不起,应该是s(是我后来更改的代码的剩余部分)。
  • 当然,我会提出一个新问题。谢谢
猜你喜欢
  • 2012-08-22
  • 1970-01-01
  • 2020-09-07
  • 2014-07-12
  • 2014-11-21
  • 2015-02-23
  • 1970-01-01
  • 2016-08-07
  • 2011-05-24
相关资源
最近更新 更多