OpenPWAStore
Back to News
Guide · May 19, 2026

Idle detection makes your PWA engagement smarter, not creepier

How to use idle detection to improve PWA performance and UX while avoiding privacy pitfalls.

OpenPWA Editorial3 min read
Idle detection makes your PWA engagement smarter, not creepier cover

为什么闲置检测对 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 标签 | | 广告定时刷新 | ❌ 禁止使用 | ✅ 固定间隔刷新 | | 社交互动限制 | ❌ 禁止使用 | ✅ 基于显式时间限制 |

下一步

  1. 需求审查:确定你的应用真的需要闲置检测,还是可以用其他方案替代
  2. 降级设计:为不支持闲置检测的浏览器准备替代方案
  3. 原型开发:先在单一功能(如后台同步)上测试效果
  4. 用户反馈:收集用户对闲置检测功能的反馈,调整隐私声明

闲置检测是强大的能力,但也是敏感的权限。透明、克制、尊重用户,才能让这个 API 真正为 PWA 体验加分。