excel 导出时根据参数获取轮询列表的所有数据

618 阅读1分钟

在很多中后台系统中很多页面都有列表数据 导出 excel 的需求,有时候是知道列表的总条数,有时候不知道,因此个人写了两个函数,用于获取列表的所有数据.


import chunk from 'lodash/chunk'

// 知道总条数
export default async (records, func, params = {}) => {
  const allList = []
  const allRes = []
  const { pageSize = 50 } = params

  let promises = []
  for (let i = 1; i < Math.ceil(+records / pageSize) + 1; i++) {
    promises.push(func({ ...params, pageNum: i, pageSize }))
    const flag = i % 5
    // pages > 5 就每次请求5页,请求完了在请求之后的数据
    if (!flag) {
      const res = await Promise.all(promises)
      allRes.push(...res)
      promises = []
    }
    // pages < 5 的情况
    if (Math.ceil(+records / pageSize) + 1 <= 5) {
      const res = await Promise.all(promises)
      allRes.push(...res)
      promises = []
    }
    // 确保最后的结尾数据都能收集到
    if (i === Math.ceil(+records / pageSize)) {
      const res = await Promise.all(promises)
      allRes.push(...res)
      promises = []
    }
  }
  allRes.forEach(e => {
    if (e instanceof Array) {
      allList.push(...e)
    }
    if (e instanceof Object && e.data instanceof Array) {
      allList.push(...e.data)
    }
  })
  return allList
}

// 不知道总条数
export async function fetchAllPageWithoutTotal({
  api,
  params = {},
  chunkSize = 50,
  concurrent = 5
} = {}) {
  const { pages = 1, data = [] } = await api({ ...params, pageNum: 1, pageSize: chunkSize })
  if (pages <= 1) return data

  const promises = []
  for (let i = 2; i <= pages; i++) {
    promises.push(
      (pageNum => () =>
        api({
          ...params,
          pageNum,
          pageSize: chunkSize
        }))(i)
    )
  }
  const allList = data
  const chunkPromises = chunk(promises, concurrent)
  for (let i = 0; i < chunkPromises.length; i++) {
    const res = await Promise.all(chunkPromises[i].map(fn => fn()))
    res.forEach(e => {
      if (Array.isArray(e)) {
        allList.push(...e)
      }
      if (e instanceof Object && Array.isArray(e.data)) {
        allList.push(...e.data)
      }
    })
  }
  return allList
}