Web Worker 简单实例应用
这篇文章由 DeathGhost 编辑,发布于
归类于 Javascript » 👋分享到微博 当前评论 0 条。
前端页面开发过程中或多或少会使用setInterval()与setTimeout()方法,这两天准备用它们做个简单的页面检测,谁料出现了问题...
最近想做个简单前端页面检测功能,设置一个毫秒数(30分钟或1个小时),实时检测,如果当前时间与初始化时间差大于所设置的时间,页面自动跳转至其他指定页面。
第一时间想到的就是setInterval()
与setTimeout()
方法,初始化刚开始还表现还挺好,可走着走着就不对劲了😂,对其执行了clearInterval()
与clearTimeout()
也无济于事,用setTimeout()
模拟setInterval()
方法也不对,其症状二次触发时间加快,页面元素触发逐渐卡顿(点击相应慢),直至整个页面卡死,最后只能强制关闭浏览器。
以前偶尔也会用到那两个方法,也没遇到这种情况。🤨
不纠结了,也看到有人说试试Web Worker,那就最后一试了,同时先大概了解下Web Worker ...
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);
}
}
这里使用onmessage
与postMessage
接收与发送。如示例,超时发送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 为超时,下面执行其他...
}
}
大概就是这样子,测试了一会,感觉没问题,暂时就这样。