继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

页面切换 定时器延迟 setInterval

潇潇雨雨
关注TA
已关注
手记 293
粉丝 25
获赞 130

最近做了一个小定时器的功能,但是在标签页切换后,定时器就会出现延迟。后面发现是在页面切换后,浏览器会自动延迟我们的定时器,以便于节约资源。

例子:开启一个定时器:0.5秒数字自增

大概6秒执行了14次


https://img.mukewang.com/5d3084e500019b2a00050017.jpg

当前页

大概11秒执行14次


https://img2.mukewang.com/5d3084ec0001db0900050004.jpg

切换标签页

在我们切换标签页后,我们的定时器根据浏览器不同,已经能明显感觉到延迟了,这个时候如果我们要保持定时器精度,可以用web work来跑我们的代码,通过在worker里面开启定时器,发送message给外部,外部收到message,然后再执行操作,这样我们切换页面,但是worker不受影响,定时器就可以解决延迟了

// time workervar intervalIds = {};// 监听message 开始执行定时器或者销毁self.onmessage = function(e){    switch(e.data.command){        case 'interval:start': // 开启定时器
            var intervalId = setInterval(function(){
                postMessage({                    message: 'interval:tick',                    id: e.data.id
                })
            },e.data.interval);

            postMessage({                message: 'interval:started',                id: e.data.id
            });

            intervalIds[e.data.id] = intervalId;            break;        case 'interval:clear': // 销毁
            clearInterval(intervalIds[e.data.id]);

            postMessage({                message: 'interval:cleared',                id: e.data.id
            })            delete intervalIds[e.data.id];            break;
    }
}

开启worker

var worker = new Worker('./time-worker.js');var workerTimer = {    id: 0,    callbacks: {},    setInterval: function(cb, interval, context) {        this.id++;        var id = this.id;        this.callbacks[id] = { fn: cb, context: context };
        worker.postMessage({ command: 'interval:start', interval: interval, id: id });        return id;
    },    // 监听worker 里面的定时器发送的message 然后执行回调函数
    onMessage: function(e) {        switch (e.data.message) {            case 'interval:tick':                var callback = this.callbacks[e.data.id];                if (callback && callback.fn) callback.fn.apply(callback.context);                break;            case 'interval:cleared':                delete this.callbacks[e.data.id];                break;
        }
    },    // 往worker里面发送销毁指令
    clearInterval: function(id) {
        worker.postMessage({ command: 'interval:clear', id: id });
    }
};

worker.onmessage = workerTimer.onMessage.bind(workerTimer);

然后我们使用的时候,直接用worker.setInterval或者workerTimer.clearInterval就可以了

https://img1.mukewang.com/5d3084f50001076d00120017.jpg

使用web worker 延迟问题就解决了

如果需要加入setTimeout,也是一样的步骤



作者:Tiny_z
链接:https://www.jianshu.com/p/3571ca7e0573


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP