如何使用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比较文档位置
Apr 08 Javascript
FireFox JavaScript全局Event对象
Jun 14 Javascript
Javascript 代码也可以变得优美的实现方法
Jun 22 Javascript
jQuery EasyUI API 中文文档 - TimeSpinner时间微调器
Oct 23 Javascript
不用构造函数(Constructor)new关键字也能实现JavaScript的面向对象
Jan 11 Javascript
深入理解JavaScript是如何实现继承的
Dec 12 Javascript
JS实现动态移动层及拖动浮层关闭的方法
Apr 30 Javascript
jquery 动态增加删除行的简单实例(推荐)
Oct 12 Javascript
EL表达式截取字符串的函数说明
Sep 22 Javascript
详解VUE2.X过滤器的使用方法
Jan 11 Javascript
彻底理解js面向对象之继承
Feb 04 Javascript
vue+webpack 更换主题N种方案优劣分析
Oct 28 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原理之变量(Variables inside PHP)
2013/08/09 PHP
PHP数据库操作之基于Mysqli的数据库操作类库
2014/04/19 PHP
php简单实现批量上传图片的方法
2016/05/09 PHP
php htmlentities()函数的定义和用法
2016/05/13 PHP
PHP中使用jQuery+Ajax实现分页查询多功能操作(示例讲解)
2017/09/17 PHP
asp批量修改记录的代码
2008/06/25 Javascript
javascript 多级checkbox选择效果
2009/08/20 Javascript
理解JavaScript变量作用域更轻松
2009/10/25 Javascript
自写的一个jQuery圆角插件
2010/10/26 Javascript
JavaScript中__proto__与prototype的关系深入理解
2012/12/04 Javascript
div模拟选择框示例代码
2013/11/03 Javascript
在百度知道团队中快速审批新成员的js脚本
2014/02/02 Javascript
js登录弹出层特效
2014/03/07 Javascript
Javascript writable特性介绍
2015/02/27 Javascript
jquery无限级联下拉菜单简单实例演示
2015/11/23 Javascript
深入JavaScript高级程序设计之对象、数组(栈方法,队列方法,重排序方法,迭代方法)
2015/12/01 Javascript
分享我对JS插件开发的一些感想和心得
2016/02/04 Javascript
使用Promise解决多层异步调用的简单学习心得
2016/05/17 Javascript
JS实现JSON.stringify的实例代码讲解
2017/02/07 Javascript
解决layer.confirm选择完之后消息框不消失的问题
2019/09/16 Javascript
python以环状形式组合排列图片并输出的方法
2015/03/17 Python
Python中的面向对象编程详解(上)
2015/04/13 Python
python开发之str.format()用法实例分析
2016/02/22 Python
Python如何使用bokeh包和geojson数据绘制地图
2020/03/21 Python
python mock测试的示例
2020/10/19 Python
对CSS3选择器的研究(详解)
2016/09/16 HTML / CSS
HTML5时代CSS设置漂亮字体取代图片
2014/09/04 HTML / CSS
美国著名的团购网站:Woot
2016/08/02 全球购物
美国顶尖折扣时尚购物网:Bluefly
2016/08/28 全球购物
经理职责范文
2013/11/08 职场文书
建筑结构施工专业推荐信
2014/02/21 职场文书
忠诚奉献演讲稿
2014/09/12 职场文书
2015毕业寄语大全
2015/02/26 职场文书
新闻简讯格式及范文
2015/07/22 职场文书
运动会800米赞词
2015/07/22 职场文书
2016年第104个国际护士节活动总结
2016/04/06 职场文书