在业务逻辑中,前端常常会碰到后端扔给你一大坨没有经过处理的数据,前端处理起来费时费力不说还得考虑性能的影响
这里针对我业务中碰到的报表导出时,大量数据循环处理导致页面渲染卡死。所写的一个通用的切片处理方法,需要的可以自己去进行改造
已验证 15000 条数据导出逻辑
已实现效果
- 可返回数据处理百分比
- 页面卡顿情况完美解决
- 导出同理可以换成其他数据处理的方法
/**
* 切片处理大量数据
*
* 问题背景:
* 1、一个 5000+ 条数据的数组进行处理
* 2、对这个数据进行切片处理
*
* 问题解决
* 1、分为两部分
*
* 例子: excel.js 的 exportCsvWithLargeData 方法
* - 传入数组,里面是固定处理的方法
* super_task 类方法
*/
function _runTask2(callback){
let start = Date.now()
requestAnimationFrame(()=>{
//时间差小于16.6毫秒,执行 16.6 毫秒为一帧渲染的时机
if(Date.now() - start < 16.6){
callback(true)
}else{
//不合适的话,我们就要重新递归调用这个_runTask函数
_runTask2(callback)
}
})
}
const arr1 = Array.from({length: 10}).map((_, num) => (num + 1) * 10)
export const handleLargeData = async (size = 50, data = [], task = () => {}, onProcess = () => {}) => {
try {
// console.time('handle')
if(data.length === 0) {
onProcess(100) // 空数据直接百分百
return []
// throw 'No Data'
}
// 分片
const step = Math.ceil(data.length / size)
// 数据缓存
let cacheData = []
// 遍历分片
for (let i = 0; i < step; i++) {
await new Promise(async (resolve, reject) => {
try {
// 执行 task 方法
const formatData = task(data.slice(i*size, (i+1)*size))
cacheData = cacheData.concat(formatData)
// 统计进度
const process = (i / step) * 100;
if(arr1.includes(Number(process.toFixed()))) {
onProcess(process)
}
// 适当暂停,避免页面无法执行渲染
await new Promise((_resolve) => {
// setTimeout(() => _resolve(true), 50);
_runTask2(_resolve)
});
resolve(true);
} catch (error) {
reject(error)
}
})
}
// 遍历完成时,固定进度为 100%
onProcess(100);
// console.log(cacheData)
// console.timeEnd('handle')
return cacheData
} catch (error) {
console.warn(error)
}
}