如何使用JS判断用户是否处于闲置状态
作者:Senar
最近在项目中遇到一个需求:需要监控用户是否开着页面但是没有操作,或者开了页面但已经离开电脑,发现了浏览器原生提供了专有的 API: IdleDetector(空闲检测器)。当然我们也可以自行实现,我们分别来聊聊这两种方式:
什么是 IdleDetector?
IdleDetector 是浏览器提供的一个实验性 API,用于检测用户的闲置状态。它可以监控以下两种状态:
- 用户状态(
user):用户是否在电脑前(通过键盘、鼠标等交互判断)。 - 屏幕状态(
screen):屏幕是否被锁定(例如屏幕保护程序启动或电脑休眠)。
目前,IdleDetector 在 Chrome 94+ 、Edge 94+ 中都支持,Firefox 和 Safari 尚未支持。但是 IdleDetector 仍为实验性 API,未来可能有变化,且在非 HTTPS 环境下无法使用。
底层原理
IdleDetector 通过浏览器底层机制检测用户和屏幕状态,开发者只需设置阈值并监听状态变化即可。API 会根据用户交互和系统状态自动判断是否进入闲置。
使用要注意
IdleDetector 需要用户授权,权限请求可通过以下两种方式触发:
- 显式请求:调用
IdleDetector.requestPermission(),需在用户手势(如点击)中触发。 - 隐式请求:直接调用
detector.start(),浏览器会自动弹出权限提示。
如果正确被调用会有这样的提示:

参考以下实现来调用:
async function startIdleDetection(threshold = 60000) {
if (!window.IdleDetector) {
console.error('浏览器不支持 IdleDetector API');
return { success: false, error: 'API_NOT_SUPPORTED' };
}
try {
// 至少要60秒, 任何小于 60 秒的设置会导致 start() 抛出 DOMException
const validatedThreshold = Math.max(threshold, 60000);
const state = await IdleDetector.requestPermission();
if (state !== 'granted') {
console.error('用户拒绝了空闲检测权限');
return { success: false, error: 'PERMISSION_DENIED' };
}
const detector = new IdleDetector();
// 添加更健壮的事件处理
const handleStateChange = () => {
const now = new Date().toISOString();
console.log(`[${now}] 用户状态: ${detector.userState}, 屏幕状态: ${detector.screenState}`);
// 实际业务逻辑可以在这里添加
if (detector.userState === 'idle') {
// 用户闲置处理
}
};
detector.addEventListener('change', handleStateChange);
// 添加错误处理
detector.addEventListener('error', (err) => {
console.error('检测器错误:', err);
});
await detector.start({ threshold: validatedThreshold });
return { success: true, detector }; // 返回检测器实例以便后续控制
} catch (err) {
console.error('空闲检测初始化失败:', err);
return { success: false, error: err.message };
}
}
// 正确用法示例(必须在用户交互中调用):
document.getElementById('startBtn').addEventListener('click', async () => {
const result = await startIdleDetection(90000); // 90秒阈值
if (!result.success) {
// 处理失败情况
}
});
如果用户拒绝了怎么办了?我们要有备选方案:
自行实现用户闲置检测
通过监听一系列浏览器事件,判断用户是否处于活跃状态。核心事件包括:
visibilitychange:检测页面是否可见(例如用户切换标签页或最小化窗口)。mousemove/mousedown/keydown/touchstart等事件:检测用户是否与页面交互。focus/blur:检测窗口是否获得焦点。
通过设置一个定时器,当用户超过一定时间未触发上述事件时,判定为闲置状态。
示例代码:
class IdleMonitor {
constructor(idleTimeout = 60000) {
this.idleTimeout = idleTimeout; // 闲置超时时间(毫秒)
this.timer = null;
this.isIdle = false;
this.handleActivity = this.handleActivity.bind(this);
this.checkIdle = this.checkIdle.bind(this);
this.init();
}
init() {
// 监听用户交互事件
['mousemove', 'mousedown', 'keydown', 'touchstart'].forEach(event => {
window.addEventListener(event, this.handleActivity);
});
// 监听页面可见性
document.addEventListener('visibilitychange', this.handleActivity);
// 启动定时器
this.startTimer();
}
handleActivity() {
if (this.isIdle) {
this.isIdle = false;
console.log('用户恢复活跃');
}
this.startTimer();
}
startTimer() {
clearTimeout(this.timer);
this.timer = setTimeout(this.checkIdle, this.idleTimeout);
}
checkIdle() {
this.isIdle = true;
console.log('用户进入闲置状态');
}
destroy() {
clearTimeout(this.timer);
['mousemove', 'mousedown', 'keydown', 'touchstart'].forEach(event => {
window.removeEventListener(event, this.handleActivity);
});
document.removeEventListener('visibilitychange', this.handleActivity);
}
}
// 使用示例
const monitor = new IdleMonitor(90000); // 90秒无操作进入闲置
这里只是举例,所以只用了点击、触摸、鼠标移动这些事件,实际上要监听的事件可能要更多一些,如 scroll、wheel、touchmove,也可以根据业务适当调整。但是对比原生的IdleDetector有一个弊端就是跨域的 iframe 中的无法监听到。跨域的 iframe 内的交互事件(如 mousemove、keydown)不会冒泡到父页面,但如果 iframe 和父页面同源,可以在 iframe 内部绑定事件监听并通过 postMessage 通知父页面。实际使用的时候也可以通过防抖或节流来优化频繁触发的事件比如 mousemove 降低性能开销。
知识延展
如何使用 JS 判断用户是否处于活跃状态
在 javascript 中我们可以通过监听某些鼠标或键盘相关的事件来判定用户是否在活跃中。
实现代码
案例演示了如何获取用户活跃状态,时间阈值定为5秒,超出该阈值没有操作表示非活跃,否则属于正在活跃中
html
<p id="userState"></p>
js
//活跃状态,true活跃中,false非活跃
let state = false;
//定时器
let timer = null;
//非活跃判定阈值,5秒没有任何活动表示非活跃
let timeout = 5000;
//用于展示状态信息的html元素
let userStateEl = document.getElementById('userState');
//批量添加事件监听
[
'mousemove', //鼠标移动
'mousedown', //鼠标按下
'touchstart', //触摸屏幕(移动端)
'wheel', //鼠标滚轮
'resize', //页面尺寸变化
'keydown', //键盘输入
]
.map(event =>{
window.addEventListener(event, onActive)
})
//触发活跃中
function onActive(){
//更新状态
state = true;
renderState();
//重置定时器
clearTimeout(timer);
timer = setTimeout(() =>{
state = false;
renderState();
}, timeout);
}
//更新状态信息
function renderState(){
if(state){
userStateEl.textContent = "活跃中 "
} else {
userStateEl.textContent = "❌非活跃状态"
}
}
//立刻触发一次活跃中
onActive();
总结
浏览器为开发者检测用户是否空闲提供了实验性的API: IdleDetector,但是需要比较新的浏览器并且需要用户显式授权,如果浏览器不支持或者用户拒绝了,我们也可以通过自行实现的方式来检测,只是有些许缺陷。
到此这篇关于如何使用JS判断用户是否处于闲置状态的文章就介绍到这了,更多相关JS判断用户状态内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
