高量级任务执行优化
项目描述:
- 运行一个耗时的任务;
- 如果要异步执行任务,请返回Promise;
- 要尽快完成任务,同时不要让页面产生卡顿;
- 尽量兼容更多的浏览器
微任务 阻塞
微任务 阻塞
执行宏任务 卡顿
requestIdleCallback 判断是否有空闲时间 兼容不好
requestAnimationFrame判断执行动画时间 可行
//执行运行任务 阻塞
function runTask1 (task){
task()
}
//异步执行任务
//为什么微任务也阻塞,因为事件循环里边,微队列一定要全部清空,才能做后边的事,包括渲染
//渲染帧是16毫秒一次,如果中间有1000个微任务,那么渲染帧就被延迟。要等待微任务全部完成之后,才会去进行渲染
function runTask2 (task){
return new Promise((resolve)=>{
Promise.resolve().then(()=>{
task()
resolve("");
})
})
}
// 执行宏任务
// 1.取出宏任务中的第一个任务. 2.执行任务 3.判断是否到达渲染时机 渲染(到了16.6毫秒他就要进行渲染了)。
//为什么卡顿?因为不同浏览器判断渲染时机的方式是不一样的
function runTask3 (task){
return new Promise((resolve)=>{
setTimeout(()=>{
task()
resolve("");
},0)
})
}
解决方案
//解决办法,手动控制人物的执行时机,就不能那么简单粗暴放到一个回调函数里面执行就完事了
//requestIdleCallback兼容相比较不好,可以使用requestAnimationFrame()函数进行替换
function _runTask1(task,callback){
//在执行任务前,判断现在运行合适吗?
//如何判断现在是否运行合适呢?判断现在还有没有空闲的时间,16.6毫秒一帧,剩下还有多少时间供我操作,如果不剩时间,我就需要回调_runTask()这个函数
//可以通过requestIdleCallback函数知道在这一帧里边我还有没有时间可以操作
requestIdleCallback((idle)=>{
//空闲时间大于0,执行
if(idle.timeRemaining() > 0){
task();
callback();
}else{
//不合适的话,我们就要重新递归调用这个_runTask函数
_runTask1(task,callback)
}
})
}
// 使用requestAnimationFrame()函数进行替换,通过时间间隔判断是否有空闲时间
function _runTask2(task,callback){
let start = Date.now();
requestAnimationFrame(()=>{
//时间差小于16.6毫秒,执行
if(Date.now() - start < 16.6){
task();
callback();
}else{
//不合适的话,我们就要重新递归调用这个_runTask函数
_runTask2(task,callback)
}
})
}
function runTask4 (task){
return new Promise((resolve)=>{
_runTask2(task(),resolve)
})
}
并发任务控制
// 执行任务类
class SuperTask{
constructor(parallelCount = 2) {
this.parallelCount = parallelCount;//并发数量
this.runningCount = 0;//正在进行的数量
this.tasks = [];//任务队列
}
add(task){
return new Promise((resolve, reject)=>{
this.tasks.push({
task,resolve,reject
})
this.handleRun()
})
}
//依次运行tasks队列的所有任务
async handleRun(){
while(this.runningCount < this.parallelCount && this.tasks.length){
//取出第一个任务
const {
task,resolve,reject} = this.tasks.shift();
//增加运行数量
this.runningCount++;
console.log(await task);
await task.then(resolve,reject).finally(()=>{
//减少运行数量
this.runningCount--;
this.handleRun();//执行下一个任务
})
}
}
}
const superTask = new SuperTask();
/** * @param time 延迟时间 * @param name 任务名 */
function addTask(time,name){
superTask.add(handleTask(time)).then(()=>{
console.log(`任务${
name}完成`);
})
}
function handleTask(time){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(time)
},time)
})
}
addTask(10000,1);//10000ms后输出,任务1完成
addTask(5000,2);//5000ms后输出,任务2完成
addTask(6000,3);//12000ms后输出,任务3完成
addTask(8000,4);//8000ms后输出,任务4完成
//每次最多执行2个任务,然后就得排队执行,所以到了第3个任务就有延迟执行了
持续更新…
踩坑不易,还希望各位大佬支持一下 \textcolor{gray}{踩坑不易,还希望各位大佬支持一下} 踩坑不易,还希望各位大佬支持一下
个人主页: \textcolor{green}{个人主页:} 个人主页: 沉默小管
我的开源系统: \textcolor{green}{我的开源系统:} 我的开源系统: VueCms_xg
技术交流 Q Q 群: 837051545 \textcolor{green}{技术交流QQ群:837051545} 技术交流QQ群:837051545
点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!
如果有不懂可以留言,我看到了应该会回复
如有错误,请多多指教
文章评论