异步

时间:2018-06-11 12:36:18

标签: angular

我是棱角分明的新人,过去几周开始学习。 我有这个包含noteId和userId的注释列表,使用UserId我需要调用另一个服务,它返回用户名。

 ngOnInit() {
    this.items.forEach(element => { 
    this.userService.loadByUserId(element.UserId)
        .subscribe(res => element.Name = res.Name) })
    }

loadByUserId包含调用User API的代码。

我正在寻找降低UserAPI负载的方法,因为this.items的数量非常庞大。

angular是否提供了一种方法,以便我可以存储先前的请求响应,并在触发第二个请求之前检查对象。对于userId

请求较高的服务器,最终游戏不会超载

我试图实现的基本上是在发送请求之前创建一个存储响应的列表,在if else中,我检查列表是否包含用户ID,名称组合,如果不是从列表返回,或者发送请求服务器。

上述方法的问题在于循环只是在其上执行或迭代100(假设?)记录,并且不等待loadByUserId方法返回响应。

请使用await / observables方法建议以角度实现此方法的最佳方法

我尝试实现此功能,但它不会发送用户API请求。

loadByUserGuid(userId: string): Observable<any> {
    return this._api.get('User/' + userId).map(res => {
      return res;
    });
  }

Observable.from(this.items).concatMap(element => this.userService.loadByUserGuid(element.UserId).do(res => element.Name = res.Name)).subscribe(() => { });

我们的想法是缓存/存储User API的响应,以避免发送多个请求

2 个答案:

答案 0 :(得分:1)

显而易见的答案是更改api以公开可以加载多个用户的loadByIDs方法。

如果无法做到这一点,您可以将请求与并发限制合并(在此示例中设置为10):

Observable.from(items)
  .mergeMap(element => 
    this.userService
      .loadByUserId(element.UserId)
      .do(res => element.Name = res.Name), 
    10) //at most 10 requests in the same time
  .subscribe(() => {}); //start doing the jobs

如果您想按顺序执行此操作,可以使用concatMap等待上一个请求完成,然后再开始新的请求:

Observable.from(items)
  .concatMap(element => 
    this.userService
      .loadByUserId(element.UserId)
      .do(res => element.Name = res.Name))
  .subscribe(() => {}); //start

答案 1 :(得分:0)

我最终使用Map来解决此问题,这就像C#词典一样。 Map返回一个可以订阅的Observable对象,从而使循环执行等待响应,然后迭代到下一个元素。

cache = new Map<string, Observable<any>>();

loadByUserId(userId: string) {
    if (userId != null) {
      if (!this.cache.has(userId)) {
        this.cache.set(userId, this._api.get('User/' + userId).pipe().shareReplay(1));
      }
      return this.cache.get(userId);
    }
    return Observable.empty();
  }