如何使用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 相关文章推荐
显示、隐藏密码
Jul 01 Javascript
js版本A*寻路算法
Dec 22 Javascript
关于javascript中this关键字(翻译+自我理解)
Oct 20 Javascript
javascript 弹出窗口中是否显示地址栏的实现代码
Apr 14 Javascript
基于JQUERY的多级联动代码
Jan 24 Javascript
基于dom编程中 动态创建与删除元素的使用
Apr 17 Javascript
window.location.href的用法(动态输出跳转)
Aug 09 Javascript
简介JavaScript中的italics()方法的使用
Jun 08 Javascript
jQuery点击弹出层弹出模态框点击模态框消失代码分享
Jan 21 Javascript
AngularJS自定义指令详解(有分页插件代码)
Jun 12 Javascript
详解angularjs 关于ui-router分层使用
Jun 12 Javascript
解决Vue项目打包后打开index.html页面显示空白以及图片路径错误的问题
Oct 25 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
关于文本留言本的分页代码
2006/10/09 PHP
PHP批量查询WordPress留言者E-mail地址实现方法
2015/02/15 PHP
php实现随机显示图片方法汇总
2015/05/21 PHP
PHP的swoole扩展安装方法详细教程
2016/05/18 PHP
两个JavaScript jsFiddle JSBin在线调试器
2010/03/14 Javascript
javascript下数值型比较难点说明
2010/06/07 Javascript
jquery监控数据是否变化(修正版)
2011/04/12 Javascript
JS获取键盘上任意按键的值(实例代码)
2013/11/12 Javascript
javascript从image转换为base64位编码的String
2014/07/29 Javascript
使用AngularJS编写较为优美的JavaScript代码指南
2015/06/19 Javascript
基于jQuery实现页面搜索功能
2020/03/26 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(一)
2017/05/11 Javascript
VUE多层路由嵌套实现代码
2017/05/15 Javascript
jQuery 添加样式属性的优先级别方法(推荐)
2017/06/08 jQuery
Vue.js 单页面多路由区域操作的实例详解
2017/07/17 Javascript
删除table表格行的实例讲解
2017/09/21 Javascript
Angular通过指令动态添加组件问题
2018/07/09 Javascript
Vue循环组件加validate多表单验证的实例
2018/09/18 Javascript
vue实现重置表单信息为空的方法
2018/09/29 Javascript
基于vue手写tree插件的那点事儿
2019/08/20 Javascript
Django使用Celery异步任务队列的使用
2018/03/13 Python
Python基础类继承重写实现原理解析
2020/04/03 Python
Python selenium 加载并保存QQ群成员,去除其群主、管理员信息的示例代码
2020/05/28 Python
Python小白垃圾回收机制入门
2020/06/09 Python
Python子进程subpocess原理及用法解析
2020/07/16 Python
Python如何读取、写入JSON数据
2020/07/28 Python
Html5 FileReader实现即时上传图片功能实例代码
2014/09/01 HTML / CSS
荷兰之家英文站:Holland at Home
2016/10/26 全球购物
Toppik顶丰增发纤维官网:解决头发稀疏
2017/12/30 全球购物
教研活动总结
2014/04/28 职场文书
2014年教师教学工作总结
2014/11/08 职场文书
2015年社区消防安全工作总结
2015/10/14 职场文书
2016应届大学生自荐信模板
2016/01/28 职场文书
退休劳动合同怎么写?
2019/10/25 职场文书
CSS3实现360度循环旋转功能
2022/02/12 HTML / CSS
sql注入报错之注入原理实例解析
2022/06/10 MySQL