0.前言
出于节能的考虑,一些浏览器(比如Chrome浏览器)会在页面进入后台等不活跃的状态时,延缓甚至暂停setTimeout等定时器的执行。在这个节能策略影响到前端页面的功能时,就需要想办法绕过此限制。
1.解决方法和原理
本人翻阅了很多网络文章,发现使用web worker是一种比较合适的解决方案。经研究理解web worker的使用方法、结合前人经验、搭配自己的调试和优化,本人编写了一段仅实现上述功能,且简洁易于理解的代码,在此将制作好的轮子分享出来,作为个人的学习记录,也希望能帮助到后来者,同时也欢迎大家友好交流。
本文不具体介绍web worker的使用方法,如需详细了解,请移步本文结尾的第3个参考文章链接。
let funtemp = function(time) {
setTimeout(function() {
self.postMessage(0);
}, time);
}
let worker = new Worker(window.URL.createObjectURL(new Blob(['(' + funtemp.toString() + ')(' + time + ')'])));
worker.onmessage = function() {
worker.terminate();
//要延迟执行的内容
}
其中funtemp函数创建了一个计时器,在time时间之后执行self.postMessage()方法,并传递一个(无意义的,此处为0)参数。createObjectURL()将上述函数封装成了一个临时url,因为worker必须由url创建。随后,创建worker并监听worker的消息。在time时间过后,worker返回消息,此时使用terminate()销毁worker释放资源,同时可以开始执行本来打算要延迟执行的代码段。
2.一个实际的例子
结合一个本人实际使用的例子:JavaScript没有sleep函数,在我们需要sleep函数功能的时候,可以通过以下代码来实现,
function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
但这样的sleep函数会被本文旨在解决的问题困扰,所以在浏览器前端使用时,将其改成下面的代码,即可完美实现功能。
function sleep(time) {
return new Promise((resolve) => {
let funtemp = function(time) {
setTimeout(function() {
self.postMessage(0);
}, time);
}
let worker = new Worker(window.URL.createObjectURL(new Blob(['(' + funtemp.toString() + ')(' + time + ')'])));
worker.onmessage = function() {
worker.terminate();
resolve();
}
});
}
3.参考内容
浏览器页面处于不活跃状态时setInterval不定时执行 - 简书