数据量大导致传输速度慢解决方案——请求分片

前言

在开发过程中,遇到要请求几千行数据的需求,因为前端部分已经使用了VirtualList虚拟列表只渲染当前可视区域的视图,非可视区域的视图在用户滚动到可视区域再渲染:
数据量大导致传输速度慢解决方案——请求分片
但仍不能解决数据加载缓慢问题。原因是数据量本身太大,导致传输的速度过慢,所以渲染到页面上的速度也很慢。


解决方案

请求分片的方式,先加载前50条数据,监听滑动到底部的事件,当列表下拉到底部的时候,再去请求后一百条数据。这么做每次只请求50条数据,传输速度就会很快。

前端具体实现如下:

function PoemList() {
  ...
  // 设置请求偏移量
  const [offset, setOffset] = useState<number>(0); 

  useEffect(() => {
	 ...
	 // 第一次请求
      getPoemList(category, offset)
        .then((res) => {
          setList(res);
        })
        .catch((err) => {
          console.error(err);
        });
    }
  }, []);
	
  // 监听滑动到底部的事件
  const handleScrollToLower = () => {
    console.log('scroll to lower!!');
    const curOffset = offset + 1;
    setOffset(curOffset);
	// 后续请求,每次请求100条数据,这个100条是在后端根据offset控制的
    getPoemList(category, curOffset)
      .then((res) => {
        setList(list.concat(res));
      })
      .catch((err) => {
        console.error(err);
      });
  };
  
  ......
  
  return (
    <View className="poemList-container">
      <View className="top">
        <View className="title">{title}</View>
        <View className="desc">{desc}</View>
      </View>

      {list.length > 0 && (
        <VirtualList
          height={800} /* 列表的高度 */
          width="100%" /* 列表的宽度 */
          itemData={list} /* 渲染列表的数据 */
          itemCount={list.length} /*  渲染列表的长度 */
          itemSize={80} /* 列表单项的高度  */
          onScrollToLower={handleScrollToLower}>
          {listItem}
        </VirtualList>
      )}
    </View>
  );
}

export default React.memo(PoemList);

后端具体实现:

const Service = require('egg').Service;

class PoemListService extends Service {
  async getPoemList(category, offset) {
    const res = await this.findPoemList(category, offset*50);

    return res;
  }

  async findPoemList(category, offset) {
    const { ctx } = this;

    // 分片获取数据
    switch (category) {
      case 0: {
        const res = await ctx.model.Poems.findAll({
          offset: offset,
          limit: 50,
        });
        return res;
      }
      case 1: {
        const res = await ctx.model.Poetry.findAll({
          offset: offset,
          limit: 50,
        });
        return res;
      }
      case 2: {
        const res = await ctx.model.Lunyu.findAll({
          offset: offset,
          limit: 50,
        });
        return res;
      }
      case 3: {
        const res = await ctx.model.Shijing.findAll({
          offset: offset,
          limit: 50,
        });
        return res;
      }
    }
  }
}
module.exports = PoemListService;

这里用到sequelizeORM。offset用于设置开始请求的偏移量(比如,如果offset为50,表示跳过前面49条数据,从第50条数据开始获取),limit表示数量。

上一篇:laravel查询出分类是否是某个用户的不是的话不让用户操作解决方案


下一篇:数据库的增删改查