Web Worker 简单实例应用

这篇文章由 DeathGhost 编辑,发布于

归类于 Javascript » 👋分享到微博 当前评论 0 条。

前端页面开发过程中或多或少会使用setInterval()与setTimeout()方法,这两天准备用它们做个简单的页面检测,谁料出现了问题...

最近想做个简单前端页面检测功能,设置一个毫秒数(30分钟或1个小时),实时检测,如果当前时间与初始化时间差大于所设置的时间,页面自动跳转至其他指定页面。

第一时间想到的就是setInterval()setTimeout()方法,初始化刚开始还表现还挺好,可走着走着就不对劲了😂,对其执行了clearInterval()clearTimeout()也无济于事,用setTimeout()模拟setInterval()方法也不对,其症状二次触发时间加快,页面元素触发逐渐卡顿(点击相应慢),直至整个页面卡死,最后只能强制关闭浏览器。

以前偶尔也会用到那两个方法,也没遇到这种情况。🤨

不纠结了,也看到有人说试试Web Worker,那就最后一试了,同时先大概了解下Web Worker ...

Web Worker 简单实例应用 - setInterval()
Web Worker 简单实例应用 - setInterval()

Web Worker 为 Web 内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。

在 worker 内,不能直接操作 DOM 节点,也不能使用 window 对象的默认方法和属性。但是你可以使用大量 window 对象之下的东西,包括 WebSockets,以及 IndexedDB 等数据存储机制。

可使用函数

atob()
btoa()
clearInterval()
clearTimeout()
setInterval()
setTimeout()
window.requestAnimationFrame
window.cancelAnimationFrame
// ...

浏览器特性检测

window.Worker

生成一个 worker

const myWorker = new Worker("worker.js");

终止 worker

myWorker.terminate();

暂时够用,更多可参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers

我项目框架是Angular,所以就按官方引导将其配置:

https://angular.io/guide/web-worker

添加一个 Web Worker

ng generate web-worker

会自动新增tsconfig.worker.json文件,同时更新相应文件。

自己定义一个文件名,最后生成一个文件

/// <reference lib="webworker" />
addEventListener('message', ({ data }) => {
  const response = `worker response to ${data}`;
  postMessage(response);
});

然后在对应组件中引用

if (typeof Worker !== 'undefined') {
  // Create a new
  const worker = new Worker(new URL('./app.worker', import.meta.url));
  worker.onmessage = ({ data }) => {
    console.log(`page got message: ${data}`);
  };
  worker.postMessage('hello');
} else {
  // Web workers are not supported in this environment.
  // You should add a fallback so that your program still executes correctly.
}

以上也是官方文档中的例子。

最后,要注意的就是若更新所创建的worker文件(e.g. timer.worker.ts)时,需要重新启动项目,方可生效,否则不生效或找不到文件。

我还是在里面放一个setInterval()方法,让其根据时间间隔执行🤣。

// timer.worker.ts
const timeout: number = 1 * 60 * 60 * 1000;
let startTime = new Date().getTime();
let timerId = null;

设定一个时间,定义一个初始化开始时间。

timerId = setInterval(() => {
 check();
}, 1000);

function check() {
  if ((new Date().getTime() - startTime) > timeout) {
    postMessage(0);
  } else {
    postMessage(1);
  }
}

这里使用onmessagepostMessage接收与发送。如示例,超时发送0。这样就可以在组件中接收到此标记,进行其他操作。

通过监听光标"mouseover",对其重置开始时间。

重置前记得先clearInterval(timerId);

this.root.addEventListener('mouseover', () => {
  const startTime = new Date().getTime();
  this.timerWorker.postMessage(startTime);
});
this.timerWorker.onmessage = async ({ data }) => {
  if (data === 0) {
    this.timerWorker.terminate();
    // ... 0 为超时,下面执行其他...
  }
}

大概就是这样子,测试了一会,感觉没问题,暂时就这样。


Web API Web Worker window.Worker setInterval() clearInterval() setTimeout() clearTimeout() 页面卡死 无响应

上一篇: