JavaScript 多线程处理计算密集型或高延迟的任务时,避免页面卡顿的方法

JavaScript 多线程处理计算密集型或高延迟的任务时,避免页面卡顿的方法

引言

  前一段时间,写了一个前端去重的博文。在处理千万级的数据时,即使不考虑兼容选用效率最高的方式,也需要几秒钟才能处理完(具体时长主要受数据重复率影响),这样会造成页面卡死的结果。因为JavsScript是单线程处理的,所以在数据未处理完时,后面的任务会等待。今天就来解决一下因任务量过大,造成的页面卡顿如何解决。

单线程处理大数据演示

单线程去重代码

// 创建一个五百万条,重复10%的数据
var arr = Array.from(new Array(5000000), function (item2, i) {
  return i % 10 < 0.1 || Math.random();
})

// 去重函数
function distinct(arr) {
  const newArray = [];
  const newMap = new Map();
  for (let i = 0, len = arr.length; i < len; i++) {
    if (!newMap.get(arr[i])) { // newMap.has(arr[i])
      newMap.set(arr[i], 1);
      newArray.push(arr[i]);
    }
  }
  return newArray;
}

// 输出耗时数据函数
function printTime(arr) {
  console.log(`数据长度:${arr.length}`)
  console.time("耗时")
  var newArr = distinct(arr)
  console.timeEnd("耗时")
  console.log(`数据重复量:${arr.length - newArr.length}`)
}

// 执行去重并后续跟随其余代码
printTime(arr)
console.log('去重后的代码执行')

动图演示

在这里插入图片描述
这里可以看到去重后面的代码,是要去重完全结束后才会去执行。还有小伙伴们可以自行把代码复制到自己的浏览器中运行,可以发现,页面会处于短暂的卡顿现象。因为JavaScript 语言采用的是单线程模型,因此中途如果处理像上方的计算密集型或高延迟的去重,就会造成页面卡顿,会给用户造成不好的体验。

多线程处理大数据演示

多线程去重代码

// 创建一个五百万条,重复10%的数据
var arr = Array.from(new Array(5000000), function (item2, i) {
  return i % 10 < 0.1 || Math.random();
})

// 去重函数
// 将要放入Worker线程的函数,此处为处理完数据后,将数据post出去,然后在主线程监听捕获。
function distinct(e) {
  const arr = e.data;
  const newArray = [];
  const newMap = new Map();
  for (let i = 0, len = arr.length; i < len; i++) {
    if (!newMap.get(arr[i])) { // newMap.has(arr[i])
      newMap.set(arr[i], 1);
      newArray.push(arr[i]);
    }
  }
  self.postMessage(newArray); 
}

// 创建Worker线程
var blob = new Blob([`
    self.addEventListener('message', ${distinct.toString()}, false);
`]); // 内部字符串内容将在Worker线程中执行,监听主线程发送来的数据,并使用上方的去重函数处理
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);

// 主线程监听worker线程返回的数据
worker.addEventListener('message', function (event) {
  console.timeEnd("耗时")
  console.log(`数据重复量:${arr.length - event.data.length}`)
  worker.terminate() // 使用完后需关闭 Worker
})

// 执行去重并后续跟随其余代码
console.log(`数据长度:${arr.length}`)
console.time("耗时")
worker.postMessage(arr) // 发送数据至Worker线程处理

console.log('去重后的代码执行')

动图演示

在这里插入图片描述
这里可以看到,去重后的代码执行不会受去重影响,去重完成后要处理的任务,会在主线程的监听Worker线程事件中触发,然后执行任务,虽然看起来耗时稍微长了,但是因为是开辟一个新的Worker线程,所以不会造成页面卡顿,用户体验就上升了。

总结

这里主要演示了在处理计算密集型或高延迟的任务时,如何让页面不卡顿,Worker 的更多使用方法可以去阮老师的教程中学习,也可以去MDN 看Worker API 和上方用到的 Blob,上述去重代码使用的是 这篇博客中Map方法去重,有兴趣的同学可以去看看。

以上如有错误或疏漏请指正,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值