在React / React Native中通过循环或递归以进度百分比获取大量数据

Shu*_*rma 5 javascript memory-leaks reactjs react-native

嗨,我正在编写一个从Android 4.4.4版到最新版的react native应用。我遇到的情况是需要下载数百万条记录,然后存储到本地数据库(使用西瓜数据库)。我正在使用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);
  };
Run Code Online (Sandbox Code Playgroud)

循环片段

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);
  };
Run Code Online (Sandbox Code Playgroud)

函数调用

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

  2. 当我们在任何形式的循环或递归中执行setState时,作为响应,它不会立即更新(批处理更新概念)。如果我想在这种情况下显示一些进度百分比,该如何显示。因为反应不会在所有迭代中都更新,所以进度将落后于实际进度。

提前致谢。

编辑

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

Faw*_*waz 0

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

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

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