OpenPWAStore
返回 News
Guide · May 19, 2026

闲置检测让 PWA 交互更智能而非更可疑

如何使用闲置检测优化 PWA 性能和体验,同时避免隐私陷阱。

OpenPWA Editorial2 min read
闲置检测让 PWA 交互更智能而非更可疑 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 体验加分。