【问题标题】:Fetching large amount of data with loop or recursion with progress percentage in React / React native在 React / React native 中使用循环或递归以进度百分比获取大量数据
【发布时间】:2019-08-09 22:44:17
【问题描述】:

您好,我正在编写一个从 Android 版本 4.4.4最新 的 react 本机应用程序。我有一种情况需要下载 数百万 条记录,然后存储到本地数据库 (using watermelon DB)。我正在对记录进行分页并使用 xhr 请求获取数据(一次 10000 个)。

获取和存储都是异步操作。我可以使用循环或递归来做到这一点。

递归片段:

dataFetch = async () => {
    if (maxPages && page > maxPages) {
      return true;
    }
    const { data } = await axios.get(API_GET_RECORDS, {
      params: {
        page,
        per_page: 10000,
      },
    });
    if (data.data && data.data.length === 0) {
      return true;
    }
    await addIntoDatabase(this.props.database, data.data);
    if ((maxPages || data.max_pages) && page) {
      this.setState({
        message: `Loading ${Number.parseFloat(
          (page * 100) / (maxPages || data.max_pages),
        )}%`,
      });
      // console.log((page * 100) / (maxPages || data.max_pages));
    }
    return this.dataFetch(page + 1, data.max_pages);
  };

循环片段

dataFetch = async () => {
    let page = 1;
    let maxPages;
    do {
      const { data } = await axios.get(API_GET_RECORDS, {
        params: {
          page,
          per_page: 10000,
        },
      });
      await addIntoDatabase(this.props.database, data.data);
      if (data.max_pages && page) {
        this.setState({
          message: `Loading ${Math.round((page * 100) / data.max_pages)}%`,
        });
      }
      page += 1;
      maxPages = data.max_pages;
    } while (page < maxPages);
  };

函数调用

downloadMyDataAndDoOtherTask = () => {
 // ... some task
 dataFetch(); // you should get all the data then start executing next line
 // ... some other task depends on this task;
}
  1. 在这种情况下最好的方法循环或递归是什么?

  2. 当我们在任何类型的循环或递归中执行 setState 时,它​​不会立即更新 (Batch update concept)。如果我想在这种情况下显示一些进度百分比,我该如何显示。因为 react 不会在所有迭代中更新,所以进度会落后于实际进度。

提前致谢。

编辑

两种方式(循环和递归)在下载大约 2-3 次缺少数据后应用程序都崩溃了。

【问题讨论】:

  • 由于您希望所有记录都存储在本地数据库中,您是否考虑过将数据库表导出到文件中并从客户端应用程序下载该文件。并读取该文件并在其上循环,并将记录存储到数据库中。您可以显示下载文件的进度。
  • 这也是个好主意。我也想到了这一点,但是时间少了,而且我在使用 react native 处理文件方面没有太多经验,我认为现在不要碰。但是感谢您的建议将在未来实施,但您现在有任何设置状态的解决方案吗?
  • 另外,文件对于后端效率不高,因为每个用户的数据不同,因此每个 api 调用服务器都必须生成文件。

标签: javascript reactjs react-native memory-leaks


【解决方案1】:

您可以使用递归方法并使用 setState 回调进行下一次迭代:

dataFetch = async () => {
  // ...
  this.setState({
    message: `Loading ${Number.parseFloat(
      (page * 100) / (maxPages || data.max_pages),
    )}%`,
  }, () => {
    InteractionManager.runAfterInteractions(() => {
      this.dataFetch(page + 1, data.max_pages);
    });
  });
};

这样,它会先把你的进度设置在 state 中,等 state 更新后继续获取。

【讨论】:

  • 我已经想到了这一点,但是代码不会等待这个函数调用完成所有数据,并且在第一次迭代之后其他部分将开始执行。我会更新 sn-p 等待。
  • 这个解决方案仍然不起作用,因为在更新状态对象不渲染后会调用回调函数。
  • @ShubhanuSharma 用InteractionManager 试试这个。更新了代码 sn-p。
  • 这也只会给出相同的响应,因为这将用于动画和交互,它不会等待渲染完成。
猜你喜欢
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
  • 2021-04-16
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-02
相关资源
最近更新 更多