今天有一个新需求,让客户端在每隔2分钟的时候执行一次某个行为,也就是计时器。
我心想,这还不简单?用setInterval一下就搞定了。
于是哼哧哼哧写完之后打开浏览器测试,让控制台每2分钟打印一次当前时间,写完打开掘金逛了一下博客去抽了一根烟。
回来的时候一看控制台,傻眼了,为什么只打印了三次,已经10分钟没打印过了。
查资料一看才知道,当客户端处于后台的时候,setInterval会停止运行,这样的话导致的问题会很严重,于是我又去搜索了一下如何实现,了解到了一个新东西:Web Worker
但我发现查资料的时候,并没有Angular8-10版本的实现方式,通过查阅文档和实验后才实现(虽然并不难),以下是实现的方法
Web Worker的定义
它允许你在后台线程中运行 CPU 密集型计算,解放主线程,以便更新用户界面。
如果你发现你的应用在处理数据时停止了响应,那么使用 Web Workers 可以为你提供帮助。
首先通过终端创建一个worker文件
ng g web-worker app
app是文件的名字,可以自定义,也可以创建后再改
在worker文件中添加一个计时器,并使用postMessage将数据传回给页面
/// <reference lib="webworker" />
addEventListener('message', ({ data }) => {
const timer = setInterval(() => {
data += 1;
postMessage(data);
console.log(data);
}, 1000);
});
在页面的ngOnInit定义并调用worker,使用onmessage获取worker传递的数据
当然,页面也是可以用postMessage传值给worker的,不过我这里只传了一个初始值0,要小心回调地狱哦
const w = new Worker('./purchase-timer.worker', { type: 'module' });
w.postMessage(0);
w.onmessage = ({ data }) => {
if (data % 120 === 0) {
console.log(moment(new Date()).format('YYYY-MM-DD HH:mm:ss') + ' 定时器正在执行...');
}
};
这样就实现了一个2分钟执行一次的计时器,即使将页面放在后台计时器也会持续运行。
参考资料:
Angular官方文档-Web Worker:v8.angular.cn/guide/web-w…
《当浏览器切换到其他标签页或者最小化时,你的js定时器还准时吗?》:juejin.cn/post/689979…