4

我正在更新@ngrx/data 下的很多记录,它在后台调用远程API 来同步数据库和本地存储。

  dataList.forEach((entity) => {
    const p = this.entitySvc
      .getEntityCollectionService(storeName)
      .upsert(entity)
      .toPromise();
    promises.push(p);
  });
  return Promise.all(promises);

我遇到的问题是远程 API 调用发生在我的代码之外,而且它发生得如此之快,连接使浏览器不堪重负:

净::ERR_INSUFFICIENT_RESOURCES

限制上面的代码没有帮助,因为远程 API 调用发生在我的控制之外。

我有办法限制 ngrx/data 远程 API 调用,还是有其他方法来解决这个问题?

4

2 回答 2

2

我会使用 mergeMap rxjs 运算符来添加服务器请求之间的并发性:

updateEntities(): Observable<any> {
  return from(dataList).pipe(
    mergeMap(entity => this.entitySvc
     .getEntityCollectionService(storeName)
     .upsert(entity), 2)
  );
}

然后在需要时调用该函数:

this.updateEntities().subscribe();

注意,mergeMap 的 concurrent 参数值为 2,表示只会并行发送 2 个请求,防止同时向服务器多次调用。您可以根据需要调整此数字。

PS:请记住,当您在 Observable 上调用 toPromise() 时,它将立即执行。

于 2020-11-23T13:41:41.643 回答
1

选项1

下面的方法使用Observable而不必先转换为承诺应该减少资源使用,试一试

  import { forkJoin } from 'rxjs'
  ...
  myFunction() {
     return forkJoin(dataList.map(entity => this.entitySvc
      .getEntityCollectionService(storeName)
      .upsert(entity)))
  }
 

注意:我们正在返回一个Observable,因此您最初调用它的位置Promise需要从 a 更改.then()为 asubscribe()

myFunction().subscribe()

选项 2

如果上述方法不能解决,请尝试以下方法。该方法链接Observable并仅在前一个请求完成后处理下一个请求。

注意:这可能会更慢,您可能需要向用户指示操作的进度

    this.dataList
      .pipe(
        tap(() => 0),
        tap(({ length }) => (this.totalItems = length)),
        flatMap(item => item)
      )
      .pipe(
        concatMap(entity =>
          this.entitySvc.getEntityCollectionService(storeName).upsert(entity)
        )
      )
      .pipe(tap(() => (this.progress += 1)))
      .subscribe({
        next: console.log
      });

看这个演示

于 2020-11-17T16:57:36.183 回答