欢迎来到[自学php网] ①群 AG亚游集团

AG亚游集团 > 前端 > javascript >

不会被 iOS 停掉的网页定时器方案

来源:未知 ?? 时间:2019-03-26 17:57?作者:小飞侠

[导读] 其实这个标题略微有点标题党:iOS 中,除了少数服务(如播放音乐),大部分 App 在用户按了 Home 键之后,过不了多久就会被完全冻结,这对 Safari 同样适用。本文不考虑这样情况,只...

其实这个标题略微有点标题党:iOS 中,除了少数服务(如播放音乐),大部分 App 在用户按了 Home 键之后,过不了多久就会被完全冻结,这对 Safari 同样适用。本文不考虑这样情况,只考虑 Safari 运行时,怎样让定时器持续工作。

我们知道:PC 上的 Firefox、Chrome 和 Safari 等浏览器,都会自动把未激活页面中的 JavaScript 定时器(setTimeout、setInterval)间隔最小值改为 1 秒以上。这是因为间隔很小的定时器一般用来做 UI 更新(例如用定时器实现的动画),让用户不可见的页面上的定时器跑慢一些,既节省资源又不会影响体验。对移动浏览器来说,内存、CPU、带宽等资源更加宝贵,移动设备上的浏览器往往会直接冻结所有未激活页面上的所有定时器。

我写了一个简单的 Demo 来说明这个问题:


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta content="width=320,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport" />
</head>
<body>
    <div id="test" style="font-size:32px;"></div>
    <script>
        var count = 0,
            test = document.getElementById('test');
        setInterval(function() {
            count++;
            test.innerHTML = count;
            document.title = count;
        }, 1 * 1000);
    </script>
</body>
</html>

在装有 iOS7 的 iPad 下测试,可以很清楚看到定时器被冻结的现象:

setInterval on iPad

但是,这种策略有时也不那么完美。对 Web 邮箱、SNS 等网站来说,让用户及时知道有新消息很重要。很多网站会定时获取消息数,有新信息时在页面标题加上消息数,这样即使用户在浏览其它 Tab 时也可以看到提醒,这种弱提醒会给用户带来良好的产品体验。iOS 上,这种做法由于定时器被冻结而变得行不通了。

既然 iOS 的浏览器(我测试了 Safari 和 Chrome)都会冻结非激活页面的 JS 定时器,那么必须另辟蹊径了。今天刚好在AG亚游集团这里看到,有个古老的页面刷新技术,无论页面是否可见都能刷新:<meta> 标签配合 refresh 属性。

简单介绍下这个 meta 头。假如页面 <head> 区有下面这行代码,页面会每隔 600s 刷新一次。

<meta http-equiv="refresh" content="600">

直接刷整个页面当然可以让页面更新,但也会把页面当前状态刷掉,还浪费流量,体验并不好。我们可以在页面引入 iframe,每次只刷新 iframe。这个 iframe 很小,流量是省了,但是每次都刷新还是会浪费 HTTP 请求,用强缓存又会使得更新很麻烦。有没有更好的办法呢?

这时候,轮到 Data URI 出场了。我们直接将含有 meta 刷新的页面 URL 编码,以 Data URI 的格式放到 iframe 的 src 中,就不会产生请求了。看下实际效果截图:

ios meta refresh

这个 Demo 的代码如下,iframe 跟主页面没有跨域,怎么传递消息都行。考虑本文讨论的是高级浏览器,我直接用的 postMessage:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta content="width=320,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport" />
    <title>后台页面更新测试 - meta refresh</title>
</head>
<body>
    <div id="test" style="font-size:32px;"></div>
    <script>
        var count = 0,
            test = document.getElementById('test');

        window.addEventListener('message', function(e) {
            if(e.data === 'refresh') {
                count++;
                test.innerHTML = count;
                document.title = count;
            }
        }, false);

        var duration = 1; /* 1s */

        var iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        iframe.src = 'data:text/html,%3C%21DOCTYPE%20html%3E%0A%3Chtml%3E%0A%3Chead%3E%0A%09%3Cmeta%20charset%3D%22utf-8%22%20%2F%3E%0A%09%3Cmeta%20http-equiv%3D%22refresh%22%20content%3D%22'+ duration +'%22%20id%3D%22metarefresh%22%20%2F%3E%0A%09%3Ctitle%3Ex%3C%2Ftitle%3E%0A%3C%2Fhead%3E%0A%3Cbody%3E%0A%09%3Cscript%3Etop.postMessage%28%27refresh%27%2C%20%27%2A%27%29%3B%3C%2Fscript%3E%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E';
        document.body.insertBefore(iframe, document.body.childNodes[0]);
    </script>
</body>
</html>

在装有 iOS7 的 iPhone 上测试,也没问题。只是 iPhone 的 Safari 在预览多标签的时候,显示的是页面的截图,所以下图中虽然整个页面一直在更新,却只能看到 Title 的变化。

iphone meta refresh

实际上,Chrome PC 版支持 <meta http-equiv="refresh" content="0.1"> 这样的小于 1 的刷新间隔,所以这种方案也可以让 Chrome PC 版不可见页面的定时器间隔小于 1s。只是浏览器的刷新按钮会闪个不停,估计没人忍受得了。

最后,在 iOS 中,使用 <meta> 方案模拟的定时器,如果需要仅在 Tab 未激活时才刷新,也很简单。代码如下:

<meta http-equiv="refresh" content="10" id="refresh">
<script>
    var meta = document.getElementById("refresh");

    setInterval(function() {
        meta.content = meta.content;
    }, parseInt(meta.content / 2) * 1000);
</script>

首先获取 meta 的刷新间隔,再设置一个间隔稍短的定时器,不断重置 meta 的刷新间隔。这样只要页面处于激活状态,meta 就没机会刷新。而页面非激活时,由于 setInterval 被冻结,页面又可以被 meta 刷新了。


最新文章

点击排行

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号@版权所有AG亚游集团

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

量化宽松不应该突然停止 欧洲央行延长3月300亿欧元 [新浪彩票]07日竞彩异常指数:申花恐怕凶多吉少 京东物流CEO王振辉:未来物流发展趋势是无界物流 中国电商京东展开宣传攻势 以吸引欧洲奢侈品牌入驻 2118年人类太空探索:勘测第九行星需百年航程 易信金融:美中贸易谈判取得进展 黄金走势不容乐观 数亿美元去向不明 马来西亚反贪机构传唤纳吉布 曝AC米兰正式邀请孔蒂执教 年薪600万欧签约3年 6.3%日本国家公务员月加班时间超“过劳死警戒线” 日本民进党与希望之党结盟计划搁浅几成定局 神射21分步行者射老鹰 格里芬25+8活塞斗公牛 对“台独”忍无可忍 台“统派”闯蔡英文父亲墓园
苏媒赞陈磊:整个生涯都是职业典范 出场必拼 曝尤文今夏挖角切尔西7000万大将 清洗1将让位 台海军演金门大停电 民众吓一跳:解放军打来了? 纳达尔:输球不意外 5个月不比赛自然做不了NO.1 中国妇女报:别把“严书记”被查归因于红颜祸水 摩根士丹利:油价2020年将升至90美元 特朗普大楼发现多个可疑物品 警方调查后排除危险 女子报警家进贼警察破门而入 打开衣柜真相太意外 《放弃我》曝万圣海报 陈乔恩王凯反差萌 金扬城6回合遭TKO落败 知难而上不畏艰险显作风 英高官抵制世界杯遭曼联名宿痛骂:没用的傻瓜! 白宫:特朗普要求中国将对美贸易顺差减少1000亿美元
粤媒称上港接过恒大外战大旗 1分能接受?就要3分 澳总理曾以这个理由赶走前任 如今面临相同窘境 三星在中国怎么就沦为了一家“1%公司”? 乐视网:佰亿投资不再参与乐融致新增资计划 京东上买茅台“被调包”成假货 山东监管部门介入 商务部:中美正在就下一步经贸磋商安排保持沟通 又淘到宝!延边0元买18岁姆巴佩式天才 忘了负心人 G20财长会议乏善可陈 日媒:美一意孤行后果很严重 美国车企盈利能力弱: 加快自动驾驶研发寻找新路径 养殖什么不愁销路 在家赚钱的十种方法 2016地摊暴利新产品 做什么生意本小利大 AG亚游集团