如何使用JS判斷用戶是否處于閑置狀態(tài)
最近在項目中遇到一個需求:需要監(jiān)控用戶是否開著頁面但是沒有操作,或者開了頁面但已經(jīng)離開電腦,發(fā)現(xiàn)了瀏覽器原生提供了專有的 API: IdleDetector(空閑檢測器)。當然我們也可以自行實現(xiàn),我們分別來聊聊這兩種方式:
什么是 IdleDetector?
IdleDetector 是瀏覽器提供的一個實驗性 API,用于檢測用戶的閑置狀態(tài)。它可以監(jiān)控以下兩種狀態(tài):
- 用戶狀態(tài)(
user):用戶是否在電腦前(通過鍵盤、鼠標等交互判斷)。 - 屏幕狀態(tài)(
screen):屏幕是否被鎖定(例如屏幕保護程序啟動或電腦休眠)。
目前,IdleDetector 在 Chrome 94+ 、Edge 94+ 中都支持,Firefox 和 Safari 尚未支持。但是 IdleDetector 仍為實驗性 API,未來可能有變化,且在非 HTTPS 環(huán)境下無法使用。
底層原理
IdleDetector 通過瀏覽器底層機制檢測用戶和屏幕狀態(tài),開發(fā)者只需設置閾值并監(jiān)聽狀態(tài)變化即可。API 會根據(jù)用戶交互和系統(tǒng)狀態(tài)自動判斷是否進入閑置。
使用要注意
IdleDetector 需要用戶授權(quán),權(quán)限請求可通過以下兩種方式觸發(fā):
- 顯式請求:調(diào)用
IdleDetector.requestPermission(),需在用戶手勢(如點擊)中觸發(fā)。 - 隱式請求:直接調(diào)用
detector.start(),瀏覽器會自動彈出權(quán)限提示。
如果正確被調(diào)用會有這樣的提示:

參考以下實現(xiàn)來調(diào)用:
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('用戶拒絕了空閑檢測權(quán)限');
return { success: false, error: 'PERMISSION_DENIED' };
}
const detector = new IdleDetector();
// 添加更健壯的事件處理
const handleStateChange = () => {
const now = new Date().toISOString();
console.log(`[${now}] 用戶狀態(tài): ${detector.userState}, 屏幕狀態(tài): ${detector.screenState}`);
// 實際業(yè)務邏輯可以在這里添加
if (detector.userState === 'idle') {
// 用戶閑置處理
}
};
detector.addEventListener('change', handleStateChange);
// 添加錯誤處理
detector.addEventListener('error', (err) => {
console.error('檢測器錯誤:', err);
});
await detector.start({ threshold: validatedThreshold });
return { success: true, detector }; // 返回檢測器實例以便后續(xù)控制
} catch (err) {
console.error('空閑檢測初始化失敗:', err);
return { success: false, error: err.message };
}
}
// 正確用法示例(必須在用戶交互中調(diào)用):
document.getElementById('startBtn').addEventListener('click', async () => {
const result = await startIdleDetection(90000); // 90秒閾值
if (!result.success) {
// 處理失敗情況
}
});
如果用戶拒絕了怎么辦了?我們要有備選方案:
自行實現(xiàn)用戶閑置檢測
通過監(jiān)聽一系列瀏覽器事件,判斷用戶是否處于活躍狀態(tài)。核心事件包括:
visibilitychange:檢測頁面是否可見(例如用戶切換標簽頁或最小化窗口)。mousemove/mousedown/keydown/touchstart等事件:檢測用戶是否與頁面交互。focus/blur:檢測窗口是否獲得焦點。
通過設置一個定時器,當用戶超過一定時間未觸發(fā)上述事件時,判定為閑置狀態(tài)。
示例代碼:
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() {
// 監(jiān)聽用戶交互事件
['mousemove', 'mousedown', 'keydown', 'touchstart'].forEach(event => {
window.addEventListener(event, this.handleActivity);
});
// 監(jiān)聽頁面可見性
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('用戶進入閑置狀態(tài)');
}
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秒無操作進入閑置
這里只是舉例,所以只用了點擊、觸摸、鼠標移動這些事件,實際上要監(jiān)聽的事件可能要更多一些,如 scroll、wheel、touchmove,也可以根據(jù)業(yè)務適當調(diào)整。但是對比原生的IdleDetector有一個弊端就是跨域的 iframe 中的無法監(jiān)聽到??缬虻?iframe 內(nèi)的交互事件(如 mousemove、keydown)不會冒泡到父頁面,但如果 iframe 和父頁面同源,可以在 iframe 內(nèi)部綁定事件監(jiān)聽并通過 postMessage 通知父頁面。實際使用的時候也可以通過防抖或節(jié)流來優(yōu)化頻繁觸發(fā)的事件比如 mousemove 降低性能開銷。
知識延展
如何使用 JS 判斷用戶是否處于活躍狀態(tài)
在 javascript 中我們可以通過監(jiān)聽某些鼠標或鍵盤相關(guān)的事件來判定用戶是否在活躍中。
實現(xiàn)代碼
案例演示了如何獲取用戶活躍狀態(tài),時間閾值定為5秒,超出該閾值沒有操作表示非活躍,否則屬于正在活躍中
html
<p id="userState"></p>
js
//活躍狀態(tài),true活躍中,false非活躍
let state = false;
//定時器
let timer = null;
//非活躍判定閾值,5秒沒有任何活動表示非活躍
let timeout = 5000;
//用于展示狀態(tài)信息的html元素
let userStateEl = document.getElementById('userState');
//批量添加事件監(jiān)聽
[
'mousemove', //鼠標移動
'mousedown', //鼠標按下
'touchstart', //觸摸屏幕(移動端)
'wheel', //鼠標滾輪
'resize', //頁面尺寸變化
'keydown', //鍵盤輸入
]
.map(event =>{
window.addEventListener(event, onActive)
})
//觸發(fā)活躍中
function onActive(){
//更新狀態(tài)
state = true;
renderState();
//重置定時器
clearTimeout(timer);
timer = setTimeout(() =>{
state = false;
renderState();
}, timeout);
}
//更新狀態(tài)信息
function renderState(){
if(state){
userStateEl.textContent = "活躍中 "
} else {
userStateEl.textContent = "?非活躍狀態(tài)"
}
}
//立刻觸發(fā)一次活躍中
onActive();
總結(jié)
瀏覽器為開發(fā)者檢測用戶是否空閑提供了實驗性的API: IdleDetector,但是需要比較新的瀏覽器并且需要用戶顯式授權(quán),如果瀏覽器不支持或者用戶拒絕了,我們也可以通過自行實現(xiàn)的方式來檢測,只是有些許缺陷。
到此這篇關(guān)于如何使用JS判斷用戶是否處于閑置狀態(tài)的文章就介紹到這了,更多相關(guān)JS判斷用戶狀態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
uniapp地圖組件(map)使用與遇到的一些問題總結(jié)
uniapp是用vue.js開發(fā)所有前端應用的框架,開發(fā)人員只需要編寫一套代碼就可以發(fā)布到安卓、iOS、H5和小程序、快應用等平臺,下面這篇文章主要給大家介紹了關(guān)于uniapp地圖組件(map)使用與遇到的一些問題,需要的朋友可以參考下2022-07-07
基于邏輯運算的簡單權(quán)限系統(tǒng)(實現(xiàn)) JS 版
基于邏輯運算的簡單權(quán)限系統(tǒng)(實現(xiàn)) JS 版...2007-03-03

