【问题标题】:Angular Material Table Asynchronously Load DataAngular 材质表异步加载数据
【发布时间】:2020-09-24 02:42:09
【问题描述】:

我有一个材料表,用于显示来自 API 调用的数据。 API 返回大量数据。为了使应用程序交互更快、更高效,我们实现了分页。例如,初始调用检索 5 条记录并呈现表。然后,我们将进行后续调用以获取其余数据。我们正在通过添加返回的数据并使用返回的数据重新呈现表格来更新数据源。

使用解析器检索初始数据(出于性能目的)。然后我在 oninit 中运行一个方法...

getTimecardSynch() {
    // Number of records to retrieve
    const pageSize = 5;
    // Call to method...passing in pageSize and pageNumber
    this._timecardManagementService
      .getIncrementalSubmittedTimecards(pageSize, this.pageNumber)
      .subscribe(
        (timecardResponse) => {
          // Increment pageNumber
          this.pageNumber++;
          // Update table datasource with retrieved data
          this.addRowData(timecardResponse);
          // Test whether pageSize is equal to the number of records returned.
          // If true, there are probably more records to retrieve and call needs made again.
          if (pageSize === timecardResponse.length) {
            // Make call to retrieve timecards again
            this.getTimecardSynch();
          } else {
            // Set the dataNotLoaded boolean to false so the interface is changed
            this.dataNotLoaded = false;
            // Show the snackbar message to the end user
            this.openSnackbar('All Timecards Loaded', '', '');
          }
        },
        (err) => {
          console.error(err);
        }
      );
  }

从上面的代码中可以看出,我有一个名为“addRowData”的方法,用于传递 API 调用返回的数据。方法如下……

  addRowData(row_obj) {
    // Add the retrieved data from the row_obj parameter to the datasource array
    this.dataSource.data.push(...row_obj);
    // Re-render the table rows
    this.table.renderRows();
    // Reload the table
    this.updateTable(this.timecards);
  }

所以我想知道是否有更好的方法可以将它们异步绑定在一起?我担心的是,正在检索的数据在此过程运行时被另一个用户更改,并可能导致重复行等。

【问题讨论】:

  • 一次检索 5 条记录似乎非常小。您是否考虑过一次检索 100 条记录,然后通过分页一次只显示 5 条记录?
  • 检索 5 条记录非常少。我们正在努力考虑我们的客户群,其中一些位于宽带几乎为零的地区。我们最初想要一个小电话来尽快获得互动。正如我们所做的那样,我们改变的一件事是我们改变了后端调用以允许检索其余记录的能力。至于分页,我们在材料表中使用它。我们试图通过取回数据和渲染来解决性能问题。这就是为什么我想知道是否有更好的异步渲染方式。
  • 可能会做一些性能测试,但我的猜测是恢复 5 条记录和恢复 100 条记录所需的时间大致相同。
  • @Rick 确实需要相同的时间,但恢复这五个可以让用户界面更快地互动。
  • 是的,我不确定这是否可能。 99% 的时间是您的网络 http 调用。获得数据后,对阵列执行拆分将花费不到 1000 秒的时间。少了很多。

标签: angular angular-material


【解决方案1】:
1. No need to push the data in this.dataSource.data because at a time will 
   display the requested data only(means based on pagination)
2. Use public dataSource = new MatTableDataSource<any>();
   this.dataSource = new MatTableDataSource(timecardResponse);
3. No need to call any method like this.addRowData(timecardResponse);

【讨论】:

  • 1) 为什么我不需要将API最近返回的数据推送到本地数据源数组?只是为了定义分页......我们通过 url 变量在 API 端进行分页。在客户端,我在材料表中启用了分页。 2)我正在使用...(数据源:MatTableDataSource;)。您是说每次调用时,我都会重新初始化数据源变量吗?这如何解决问题? 3)你是说你会把push和render集成到get方法中而不是分开吗?如果是这样,我理解,但不能解决我的问题。想法?
【解决方案2】:

如果由于 observable 的一些变化而两次接收到相同的数据,你可以尝试 rxjs 中的distinctUntilChanged 运算符。如果当前值与上一个不同,此运算符将使 observable 仅发出值。

const incrementalSubmittedTimecards$ = this._timecardManagementService
  .getIncrementalSubmittedTimecards(pageSize, this.pageNumber).pipe(distinctUntilChanged());

incrementalSubmittedTimecards$.subscribe(...);

如果你想在两次连续发射之间有一个时间间隔并且只获取最新的数据,你可以尝试 rxjs 中的debounce 运算符。此运算符不会考虑在指定时间内发出的任何值,并且只考虑指定时间结束时的最新值。

const incrementalSubmittedTimecards$ = this._timecardManagementService
  .getIncrementalSubmittedTimecards(pageSize, this.pageNumber).pipe(debounce(() => timer(1000)));

incrementalSubmittedTimecards$.subscribe(...);

如果我的理解有误,请纠正我。谢谢

【讨论】:

  • 谢谢...我会牢记这些技巧。我成功地用 5 实现了它,然后是其余的。我只是想知道是否有更好的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
  • 2019-12-21
  • 2018-06-17
  • 1970-01-01
  • 2018-09-02
  • 2019-11-25
相关资源
最近更新 更多