如何使用JavaScript检测空闲的浏览器选项卡


Posted in Javascript onMay 28, 2020

在某些情况下,当用户与我们的最终产品或应用程序进行交互时,我们发现自己会执行许多密集的,占用大量CPU的任务。启动轮询器,建立WebSocket连接,甚至加载视频或图片等媒体,都有可能成为性能障碍,尤其是当这些任务在不需要的情况下消耗资源的时候。

在用户没有主动与界面交互的同时,从不必要的工作负载或网络请求中释放主线程是一个非常好的和有意义的实践。换一种方式,在大多数主机提供商都在引入基于配额的定价模式的行业中,减少网络请求也可以降低运行应用程序或服务的成本。

如何使用JavaScript检测空闲的浏览器选项卡

页面可见性(Page Visibility) API

所有现代的网页浏览器都加入了页面可见性API,它允许我们检测浏览器的标签页何时被隐藏,此外,我们还可以注册一个事件监听器,以检测可见性变化时的信号。

document.visibilityState

当页面处于前台时,document.visibilityState 可能是 visible ,最小化窗口的“标签”或隐藏。

我们可以通过以下方式直接访问 document.visibilityState:

console.log(document.visibilityState); 
// => 它可以是“visible”或“hidden”

visibilitychange Event

我们还可以使用事件侦听器轻松检测可见性属性中的更改。

const onVisibilityChange = () => { 
 if (document.visibilityState === 'hidden') { 
  console.log('> 这个窗口是隐藏的.'); 
 } else { 
  console.log('> 这个窗口是可见的.'); 
 } 
}; 
document.addEventListener('visibilitychange', onVisibilityChange, false);

轮询示例

考虑一种情况,在这种情况下,我们正在轮询API以获取更新,并且希望避免对空闲用户进行不必要的调用。一个简化的示例如下所示:

const poll = () => { 
 const interval = 1500; 
 let _poller = null; 
 const repeat = () => { 
  console.log(`~ Polling: ${Date.now()}.`); 
 }; 
 
 return { 
  start: () => { 
   _poller = setInterval(repeat, interval); 
  }, 
  stop: () => { 
   console.log('~ Poller stopped.'); 
   clearInterval(_poller); 
  } 
 }; 
}; 
 
const poller = poll(); 
poller.start(); 
 
const onVisibilityChange = () => { 
 if (document.visibilityState === 'hidden') { 
  poller.stop(); 
 } else { 
  poller.start(); 
 } 
}; 
 
document.addEventListener('visibilitychange', onVisibilityChange, false);

在后台异步加载

但有时我们可以通过反其道而行之,加速用户的终端体验。我们可以异步加载外部依赖或资产,而不是取消所有的作业和请求。这样,当用户回来时,他们的最终体验将更加“充实”并且丰富。

如何使用JavaScript检测空闲的浏览器选项卡

/ Webpack /

使用ES2015动态导入建议和适当的Webpack配置清单,我们可以轻松地在后台加载额外的模块或资产。

let loaded = false; 
const onVisibilityChange = () => { 
 if (document.visibilityState === 'hidden') { 
  // Aggresively preload external assets ans scripts 
  if (loaded) { 
   return; 
  } 
  Promise.all([ 
   import('./async.js'), 
   import('./another-async.js'), 
   import(/* webpackChunkName: "bar-module" */ 'modules/bar'), 
   import(/* webpackPrefetch: 0 */ 'assets/images/foo.jpg') 
  ]).then(() => { 
   loaded = true; 
  }); 
 } 
}; 
 
document.addEventListener('visibilitychange', onVisibilityChange, false);

/ Rollup /

Rollup还支持开箱即用的动态导入。

let loaded = false; 
const onVisibilityChange = () => { 
 if (document.visibilityState === 'hidden') { 
  // Aggresively preload external assets ans scripts 
  if (loaded) { 
   return; 
  } 
  Promise.all([ 
   import('./modules.js').then(({default: DefaultExport, NamedExport}) => { 
    // do something with modules. 
   }) 
  ]).then(() => { 
   loaded = true; 
  }); 
 } 
}; 
 
document.addEventListener('visibilitychange', onVisibilityChange, false);

/ 用Javascript预加载 /

除了使用捆绑器,我们还可以仅使用几行JavaScript来预加载静态资源(例如图像)。

let loaded = false; 
const preloadImgs = (...imgs) => { 
 const images = []; 
 imgs.map( 
  url => 
   new Promise((resolve, reject) => { 
    images[i] = new Image(); 
    images[i].src = url; 
    img.onload = () => resolve(); 
    img.onerror = () => reject(); 
   }) 
 ); 
}; 
const onVisibilityChange = () => { 
 if (document.visibilityState === 'hidden') { 
  // Aggresively preload external assets ans scripts 
  if (loaded) { 
   return; 
  } 
  Promise.all( 
   preloadImgs( 
    'https://example.com/foo.jpg', 
    'https://example.com/qux.jpg', 
    'https://example.com/bar.jpg' 
   ) 
  ) 
   .then(() => { 
    loaded = true; 
   }) 
   .catch(() => { 
    console.log('> Snap.'); 
   }); 
 } 
}; 
document.addEventListener('visibilitychange', onVisibilityChange, false);

微互动

最后,一种吸引用户注意力的巧妙方法是动态更改图标,只需使用几个像素就可以保持交互。

const onVisibilityChange = () => { 
 const favicon = document.querySelector('[rel="shortcut icon"]'); 
 if (document.visibilityState === 'hidden') { 
  favicon.href = '/come-back.png'; 
 } else { 
  favicon.href = '/example.png'; 
 } 
}; 
 
document.addEventListener('visibilitychange', onVisibilityChange, false);

总结

到此这篇关于如何使用JavaScript检测空闲的浏览器选项卡的文章就介绍到这了,更多相关js浏览器选项卡内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
Javascript attachEvent传递参数的办法
Dec 14 Javascript
js函数获取html中className所在的内容并去除标签
Sep 08 Javascript
Bootstrap 折叠(Collapse)插件用法实例详解
Jun 01 Javascript
Node.js 异步异常的处理与domain模块解析
May 10 Javascript
基于react框架使用的一些细节要点的思考
May 31 Javascript
JavaScript输入分钟、秒倒计时技巧总结(附代码)
Aug 17 Javascript
vue-router 起步步骤详解
Mar 26 Javascript
JS实现选项卡效果的代码实例
May 20 Javascript
vue配置文件实现代理v2版本的方法
Jun 21 Javascript
vue 的 solt 子组件过滤过程解析
Sep 07 Javascript
Vue如何实现监听组件原生事件
Jul 03 Javascript
javascript实现简单留言板案例
Feb 09 Javascript
js实现轮播图特效
May 28 #Javascript
JS写滑稽笑脸运动效果
May 28 #Javascript
Python版实现微信公众号扫码登陆
May 28 #Javascript
基于aotu.js实现微信自动添加通讯录中的联系人功能
May 28 #Javascript
原生js实现五子棋游戏
May 28 #Javascript
Vue微信公众号网页分享的示例代码
May 28 #Javascript
纯JS实现五子棋游戏
May 28 #Javascript
You might like
比较简单实用的PHP无限分类源码分享(思路不错)
2011/10/13 PHP
CentOS 6.3下安装PHP xcache扩展模块笔记
2014/09/10 PHP
CentOS 7.2 下编译安装PHP7.0.10+MySQL5.7.14+Nginx1.10.1的方法详解(mini版本)
2016/09/01 PHP
php车辆违章查询数据示例
2016/10/14 PHP
CL vs ForZe BO5 第五场 2.13
2021/03/10 DOTA
jQuery 动画弹出窗体支持多种展现方式
2010/04/29 Javascript
IE6 fixed的完美解决方案
2011/03/31 Javascript
新增加的内容是如何将div的scrollbar自动移动最下面
2014/01/02 Javascript
Node.js 应用跑得更快 10 个技巧
2016/04/03 Javascript
JavaScript实现的微信二维码图片生成器的示例
2016/10/26 Javascript
javascript简单进制转换实现方法
2016/11/24 Javascript
原生JS实现导航下拉菜单效果
2020/11/25 Javascript
20行JS代码实现网页刮刮乐效果
2017/06/23 Javascript
关于JavaScript中的this指向问题总结篇
2017/07/23 Javascript
layer子层给父层页面元素赋值,以达到向父层页面传值的效果实例
2017/09/22 Javascript
关于jquery中attr()和prop()方法的区别
2018/05/28 jQuery
vue删除html内容的标签样式实例
2018/09/13 Javascript
浅谈微信小程序列表埋点曝光指南
2019/10/15 Javascript
微信小程序顶部导航栏可滑动并选中放大
2019/12/05 Javascript
JavaScript鼠标拖拽事件详解
2020/04/03 Javascript
解决Vue项目中tff报错的问题
2020/10/21 Javascript
如何正确解决VuePress本地访问出现资源报错404的问题
2020/12/03 Vue.js
video.js添加自定义组件的方法
2020/12/09 Javascript
[01:32]TI奖金增速竟因它再创新高!DOTA2勇士令状不朽珍藏Ⅰ饰品欣赏
2018/05/18 DOTA
[01:04:05]VG vs Newbee 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Python 解析XML文件
2009/04/15 Python
python与php实现分割文件代码
2017/03/06 Python
对python模块中多个类的用法详解
2019/01/10 Python
Python利用Pillow(PIL)库实现验证码图片的全过程
2020/10/04 Python
CSS3 clip-path 用法介绍详解
2018/03/01 HTML / CSS
HTML5 WebGL 实现民航客机飞行监控系统
2019/07/25 HTML / CSS
Spartoo葡萄牙鞋类网站:线上销售鞋履与时尚配饰
2017/01/11 全球购物
Clarks鞋澳大利亚官方网站:Clarks Australia
2019/12/25 全球购物
2017年寒假少先队活动总结
2016/04/06 职场文书
如何用JavaScript检测当前浏览器是无头浏览器
2021/04/27 Javascript
Go Plugins插件的实现方式
2021/08/07 Golang