Idle detection makes your PWA engagement smarter, not creepier
How to use idle detection to improve PWA performance and UX while avoiding privacy pitfalls.
为什么闲置检测对 PWA 交互很重要
闲置检测 API 让 PWA 可以感知用户何时活跃、闲置或锁屏,从而调整应用行为:
- 智能资源管理:在用户闲置时执行耗时操作(如数据同步、缓存更新)
- 隐私保护:避免在用户活跃时发出侵入性通知
- 性能优化:减少主线程渲染压力,在闲置时执行低优先级任务
- 体验提升:根据用户状态调整 UI(如闲置时显示节省模式)
MDN 文档强调,此 API 可在无需轮询的情况下检测用户闲置状态,对于聊天应用显示在线状态、在用户交互时发送通知等场景尤其有用。
重要警告:这是一个实验性 API,并非所有浏览器都支持。使用前必须检查兼容性并做好降级处理。
如何实施闲置检测
步骤 1:检查支持并请求权限
// 1. 检查 API 是否可用
if (!('IdleDetector' in window)) {
console.log('IdleDetector not supported in this browser');
// 提供降级方案
return;
}
// 2. 检查权限
const permissionStatus = await navigator.permissions.query({
name: 'idle-detection',
});
if (permissionStatus.state === 'denied') {
console.log('Idle detection permission denied');
return;
}
// 3. 请求权限(需要用户激活)
const permission = await IdleDetector.requestPermission();
if (permission !== 'granted') {
console.error('Idle detection permission not granted');
return;
}步骤 2:创建闲置检测器
const controller = new AbortController();
const signal = controller.signal;
async function startIdleDetection() {
try {
const idleDetector = new IdleDetector();
// 监听状态变化
idleDetector.addEventListener('change', () => {
const { userState, screenState } = idleDetector;
console.log(`Idle state changed: user=${userState}, screen=${screenState}`);
handleIdleStateChange(userState, screenState);
});
// 启动检测
await idleDetector.start({
threshold: 60_000, // 60秒无操作视为闲置
signal,
});
console.log('IdleDetector is active');
} catch (err) {
console.error('IdleDetector failed:', err.name, err.message);
// 处理错误(权限拒绝、非顶级 frame 等)
}
}步骤 3:根据状态调整应用行为
function handleIdleStateChange(userState, screenState) {
switch (userState) {
case 'active':
// 用户活跃,恢复全功能
enableRealtimeFeatures();
showDynamicContent();
break;
case 'idle':
// 用户闲置,执行后台任务
scheduleBackgroundSync();
deferNonCriticalUpdates();
break;
case 'locked':
// 屏幕已锁,完全静默
pauseAllOperations();
break;
}
// 屏幕状态也可以影响行为
if (screenState === 'locked') {
enterPowerSavingMode();
}
}步骤 4:清理和停止
function stopIdleDetection() {
controller.abort();
console.log('IdleDetector stopped');
}
// 在页面卸载时清理
window.addEventListener('beforeunload', stopIdleDetection);闲置检测应用场景检查清单
✅ 推荐使用场景
- [ ] 后台数据同步:用户闲置时同步缓存、更新数据
- [ ] 智能通知:只在用户活跃时发送推送,避免打扰
- [ ] 性能优化:在闲置时预加载下一页内容
- [ ] 资源清理:清理过期缓存、临时文件
- [ ] 在线状态管理:聊天应用显示真实的活跃状态
⚠️ 谨慎使用场景
- [ ] 自适应内容:根据闲置状态调整 UI 难度/密度
- [ ] 暂停媒体:闲置时暂停非关键音视频
- [ ] 收集分析数据:仅用于性能优化,不追踪用户习惯
❌ 禁止使用场景
- [ ] 侵入性监控:记录用户闲置时间用于定向广告
- [ ] 强制行为:闲置时强制登录/付费/限制功能
- [ ] 隐私泄露:闲置检测数据与个人身份关联
- [ ] 绕过用户授权:在隐藏 frame 中启动闲置检测
隐私和伦理准则
透明度
- [ ] 明确告知:在设置页面说明应用会检测闲置状态
- [ ] 用途说明:清晰解释为何需要闲置检测(如"优化性能","智能通知")
- [ ] 数据不存储:不要将闲置检测数据上传到服务器
控制权
- [ ] 可关闭:用户可以禁用闲置检测功能
- [ ] 最小化使用:仅在必要的功能中使用闲置检测
- [ ] 降级方案:浏览器不支持时仍可正常使用应用
用户体验
- [ ] 渐进增强:对支持闲置检测的浏览器提供更好体验
- [ ] 无法感知:闲置检测不应影响应用立即可用性
- [ ] 快速反馈:闲置状态变化应有即时 UI 反馈(如状态栏图标)
对开发者意味着什么
产品设计
- 性能优化:闲置检测让资源使用更智能,延长电池续航
- 体验提升:避免在用户操作时执行阻塞任务
- 差异化竞争:精细化的资源管理成为产品优势
技术债务
- 浏览器兼容性:需要为不支持此 API 的浏览器提供降级方案
- 调试复杂度:闲置状态变化难以直接观察,需要日志和状态追踪
- 权限管理:需要妥善处理权限拒绝、撤销等边缘情况
风险评估
- 隐私担忧:闲置检测可能被误解为"监控",需充分沟通
- 实验性风险:API 可能被弃用或更改,需关注浏览器更新
- 平台差异:不同浏览器的闲置行为可能不一致
决策框架
| 场景 | 使用闲置检测 | 不使用闲置检测 | |------|--------------|----------------| | 大文件后台下载 | ✅ 在闲置时开始下载 | ❌ 可能占用主线程 | | 聊天应用在线状态 | ✅ 实时更新状态 | ⚠️ 使用心跳机制 | | 新闻内容预加载 | ✅ 闲置时预读预缓存 | ⚠️ 仅在滚动时加载 | | 游戏暂停静音 | ⚠️ 可选性功能 | ❌ 直接使用 audio 标签 | | 广告定时刷新 | ❌ 禁止使用 | ✅ 固定间隔刷新 | | 社交互动限制 | ❌ 禁止使用 | ✅ 基于显式时间限制 |
下一步
- 需求审查:确定你的应用真的需要闲置检测,还是可以用其他方案替代
- 降级设计:为不支持闲置检测的浏览器准备替代方案
- 原型开发:先在单一功能(如后台同步)上测试效果
- 用户反馈:收集用户对闲置检测功能的反馈,调整隐私声明
闲置检测是强大的能力,但也是敏感的权限。透明、克制、尊重用户,才能让这个 API 真正为 PWA 体验加分。