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

时间:2019-03-19 11:52:45

标签: javascript reactjs react-native memory-leaks

嗨,我正在编写一个从Android版本 4.4.4 最新的react native应用。我遇到一种情况,需要下载数百万条记录,然后将其存储到本地数据库(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.   
  3. 在以任何形式的循环或递归执行setState时,在反应中它不会立即更新(Batch update concept)。如果我想在这种情况下显示一些进度百分比,该如何显示。因为反应不会在所有迭代中都更新,所以进度将落后于实际进度。

  4.   

谢谢。

修改

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

1 个答案:

答案 0 :(得分: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);
    });
  });
};

通过这种方式,它将首先设置您的状态进度,并在状态更新后继续获取。