如何使用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 相关文章推荐
jQuery Ajax使用 全解析
Dec 15 Javascript
关于event.cancelBubble和event.stopPropagation()的区别介绍
Dec 11 Javascript
JavaScript高级程序设计 阅读笔记(十七) js事件
Aug 14 Javascript
JQuery右键菜单插件ContextMenu使用指南
Dec 19 Javascript
jquery中ajax跨域方法实例分析
Dec 18 Javascript
jquery 全选、全不选、反选效果的实现代码【推荐】
May 05 Javascript
详解XMLHttpRequest(二)响应属性、二进制数据、监测上传下载进度
Sep 14 Javascript
利用JS对iframe父子(内外)页面进行操作的方法教程
Jun 15 Javascript
推荐15个最好用的JavaScript代码压缩工具
Feb 13 Javascript
js模拟F11页面全屏显示
Sep 17 Javascript
微信小程序跳转到其他网页(外部链接)的实现方法
Sep 20 Javascript
Openlayers实现点闪烁扩散效果
Sep 24 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+MySQL 手工注入语句大全 推荐
2009/10/30 PHP
php下使用iconv需要注意的问题
2010/11/20 PHP
PHPUnit PHP测试框架安装方法
2011/03/23 PHP
php实现四舍五入的方法小结
2015/03/03 PHP
PHP集成环境XAMPP的安装与配置
2018/11/13 PHP
php下的原生ajax请求用法实例分析
2020/02/28 PHP
[推荐]javascript 面向对象技术基础教程
2009/03/03 Javascript
Jquery Ajax学习实例6 向WebService发出请求,返回DataSet(XML) 异步调用
2010/03/18 Javascript
javascript字符串拼接的效率问题
2010/12/25 Javascript
javascript中length属性的探索
2011/07/31 Javascript
javascript从右边截取指定字符串的三种实现方法
2013/11/29 Javascript
JS父页面与子页面相互传值方法
2014/03/05 Javascript
JavaScript通过this变量快速找出用户选中radio按钮的方法
2015/03/23 Javascript
JS制作手机端自适应缩放显示
2015/06/11 Javascript
jQuery遍历节点树方法分析
2016/09/08 Javascript
基于JavaScript实现窗口拖动效果
2017/01/18 Javascript
html5 canvas 详细使用教程
2017/01/20 Javascript
Vuex 入门教程
2018/01/10 Javascript
vue中使用cropperjs的方法
2018/03/01 Javascript
跟混乱的页面弹窗说再见
2019/04/11 Javascript
JS中的变量作用域(console版)
2020/07/18 Javascript
vue实践---vue不依赖外部资源实现简单多语操作
2020/09/21 Javascript
在antd中setFieldsValue和defaultVal的用法
2020/10/29 Javascript
[02:40]DOTA2超级联赛专访430 从小就爱玩对抗性游戏
2013/06/18 DOTA
python抓取京东价格分析京东商品价格走势
2014/01/09 Python
python traceback捕获并打印异常的方法
2018/08/31 Python
Python实现账号密码输错三次即锁定功能简单示例
2019/03/29 Python
python SQLAlchemy 中的Engine详解
2019/07/04 Python
Pytorch转tflite方式
2020/05/25 Python
浅谈keras 模型用于预测时的注意事项
2020/06/27 Python
Django Session和Cookie分别实现记住用户登录状态操作
2020/07/02 Python
Django生成数据库及添加用户报错解决方案
2020/10/09 Python
英国比较机场停车场网站:Airport Parking Essentials
2019/12/01 全球购物
2016年春节慰问信息
2015/03/25 职场文书
Java 超详细讲解ThreadLocal类的使用
2022/04/07 Java/Android