You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Angular 9中获取用户空闲时长(分钟)

刚好我之前做过类似的会话超时功能,获取用户空闲时间的核心思路其实就是监听用户的交互行为,记录最后一次活跃的时间,再和当前时间对比计算差值。下面给你详细讲讲Angular里的实现思路和具体代码:

核心思路

获取用户空闲分钟数的本质是追踪用户最后一次交互的时间戳,然后通过「当前时间 - 最后活跃时间」的差值计算空闲时长。结合你60分钟的会话总时长,就能算出会话剩余的过期时间:会话剩余时长 = 总时长 - 空闲时长。

具体实现步骤

我推荐把这个逻辑封装成一个Angular服务,方便在整个应用中复用:

1. 创建IdleService服务

这个服务负责监听用户交互、计算空闲时间、检查会话剩余时长,以及触发超时提示:

import { Injectable, OnDestroy } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class IdleService implements OnDestroy {
  // 记录最后一次用户活跃的时间戳
  private lastActiveTime: number = Date.now();
  // 定时检查的定时器实例
  private idleCheckTimer?: NodeJS.Timeout;
  // 会话总时长(60分钟,转成毫秒)
  private readonly sessionDurationMs = 60 * 60 * 1000;
  // 每5秒检查一次空闲状态(可根据需求调整)
  private readonly checkIntervalMs = 5 * 1000;

  constructor() {
    // 初始化用户交互监听
    this.setupUserActivityListeners();
    // 启动空闲检查定时器
    this.startIdleCheck();
  }

  // 监听用户核心交互事件
  private setupUserActivityListeners(): void {
    // 选择常见的交互事件,避免监听过多影响性能
    const activityEvents = ['mousemove', 'keydown', 'click', 'scroll', 'touchstart'];
    activityEvents.forEach(event => {
      document.addEventListener(event, () => this.updateLastActiveTime());
    });
  }

  // 更新最后活跃时间
  private updateLastActiveTime(): void {
    this.lastActiveTime = Date.now();
    // 这里记得通知后端刷新会话有效期!
    // 比如调用一个后端接口,告诉服务器用户还在活跃,延长会话
    // this.http.post('/api/refresh-session', {}).subscribe();
  }

  // 获取当前空闲分钟数
  public getIdleMinutes(): number {
    const idleMs = Date.now() - this.lastActiveTime;
    return Math.floor(idleMs / 60000);
  }

  // 获取会话剩余过期分钟数
  public getRemainingSessionMinutes(): number {
    const elapsedMs = Date.now() - this.lastActiveTime;
    const remainingMs = this.sessionDurationMs - elapsedMs;
    // 确保剩余时间不会为负数
    return Math.max(0, Math.floor(remainingMs / 60000));
  }

  // 启动定时检查逻辑
  private startIdleCheck(): void {
    this.idleCheckTimer = setInterval(() => {
      const remainingMinutes = this.getRemainingSessionMinutes();
      
      // 剩余5分钟时弹出延长会话提示
      if (remainingMinutes <= 5 && remainingMinutes > 0) {
        this.showSessionExtendPrompt(remainingMinutes);
      } 
      // 会话已过期,执行超时逻辑
      else if (remainingMinutes === 0) {
        this.handleSessionTimeout();
      }
    }, this.checkIntervalMs);
  }

  // 弹出延长会话提示
  private showSessionExtendPrompt(remainingMinutes: number): void {
    // 这里可以替换成你自己的模态框组件
    const shouldExtend = confirm(`你的会话将在${remainingMinutes}分钟后过期,是否延长会话?`);
    if (shouldExtend) {
      // 用户确认后,更新活跃时间(相当于延长会话)
      this.updateLastActiveTime();
    }
  }

  // 会话过期后的处理逻辑
  private handleSessionTimeout(): void {
    // 比如跳转到登录页,清除本地会话数据
    localStorage.removeItem('authToken');
    window.location.href = '/login';
  }

  // 组件销毁时清理资源,避免内存泄漏
  ngOnDestroy(): void {
    const activityEvents = ['mousemove', 'keydown', 'click', 'scroll', 'touchstart'];
    activityEvents.forEach(event => {
      document.removeEventListener(event, () => this.updateLastActiveTime());
    });
    if (this.idleCheckTimer) {
      clearInterval(this.idleCheckTimer);
    }
  }
}

2. 在组件中使用服务

你可以在AppComponent或者任何需要的组件中注入这个服务,比如:

import { Component } from '@angular/core';
import { IdleService } from './services/idle.service';

@Component({
  selector: 'app-root',
  template: `
    <div>会话剩余时长:{{ idleService.getRemainingSessionMinutes() }} 分钟</div>
  `
})
export class AppComponent {
  constructor(public idleService: IdleService) {}
}
关键注意事项
  • 后端同步:前端更新活跃时间后,一定要调用后端接口刷新会话有效期,否则后端的会话还是会按时过期。
  • 事件选择:不要监听太多事件,选mousemove、keydown这类核心交互事件即可,避免不必要的性能开销。
  • 定时器间隔:建议设置5-10秒的检查间隔,太频繁会增加CPU负载,太稀疏会导致提示不及时。
  • 多标签页适配:如果你的应用支持多标签页,可以用localStorage同步最后活跃时间,避免不同标签页的空闲时间计算不一致。
  • 移动端适配:一定要加上touchstart这类触摸事件,确保移动端用户的交互能被捕获。

内容的提问来源于stack exchange,提问作者biju m

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 21:48:11