基于RxJS实现Angular应用的浏览器空闲状态追踪方案验证
Angular 浏览器空闲状态追踪与自动登出实现优化
需求说明
需要在Angular应用中追踪浏览器的空闲/无活动状态,当用户连续5分钟无交互操作时触发自动登出逻辑,且要求在客户端生命周期内,每次出现无活动状态都能收到通知。
初始实现代码
用户最初编写的RxJS实现如下:
import {filter, from, fromEvent, mergeAll, Observable, of, repeat, timeout} from 'rxjs'; const timeoutDelay = 1000 * 60 * 5; // 5分钟 const events = ['keypress', 'click', 'wheel', 'mousemove', 'ontouchstart']; const $onInactive = from(events.map(e => fromEvent(document, e))) .pipe( mergeAll(), timeout({each: timeoutDelay, with: () => of(undefined as any)}), filter(a => !a), repeat() );
初始代码使用方式
$onInactive.subscribe(() => { // 用户已5分钟无活动 // 如果当前处于登录状态,则执行登出操作 });
初始实现的问题
虽然上述代码能正常运行,但存在可优化点:
- 事件流合并方式不够简洁:使用
from配合mergeAll不如直接用merge操作符合并多个事件流高效直观 - 空闲触发逻辑可读性差:通过
timeout返回undefined再过滤的方式,逻辑不够直白,维护成本高 - 未遵循Angular最佳实践:没有封装为可注入的服务,不利于复用和全局管理
优化后的Angular v15服务实现
以下是符合Angular最佳实践的优化实现,封装为全局单例服务:
import {Injectable} from '@angular/core'; import { Observable, fromEvent, interval, merge, repeat, takeUntil, map, } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class InactivityService { readonly timeoutDelay = 1000 * 60 * 5; // 5分钟 readonly $onIdle: Observable<void>; constructor() { const events = ['keypress', 'click', 'wheel', 'mousemove', 'ontouchstart']; // 合并所有用户交互事件流 const $activitySignal = merge(...events.map(eventName => fromEvent(document, eventName))); // 构建空闲通知流:每隔timeoutDelay触发,若有用户交互则重置计时 this.$onIdle = interval(this.timeoutDelay) .pipe( takeUntil($activitySignal), map(() => undefined), repeat() ); } }
优化后代码的使用示例
在组件或其他服务中注入InactivityService即可使用:
constructor(private inactivityService: InactivityService) { this.inactivityService.$onIdle.subscribe(() => { // 用户已空闲5分钟 // 该通知会在每次用户空闲时重复触发 // 执行自动登出逻辑 }); }
内容的提问来源于stack exchange,提问作者vitaly-t
相关产品推荐
相关产品推荐

