ReactJS如何在浏览器或标签页关闭时调用log out api
浏览器/标签页关闭时自动触发登出API的实现方案
首选实现方案:beforeunload 结合 sendBeacon
这是目前兼容性和体验最优的方案,sendBeacon是浏览器专门为页面卸载场景设计的API,会保证请求异步发送且不阻塞页面关闭,就算标签页已经销毁,浏览器也会在后台尽力完成请求发送。
实现代码如下:
window.addEventListener('beforeunload', () => { // 构造登出接口需要的参数 const logoutParams = new FormData(); logoutParams.append('user_token', localStorage.getItem('current_user_token')); // 发送登出请求 const requestQueued = navigator.sendBeacon('/api/user/logout', logoutParams); // 当sendBeacon入队失败(如数据超出64KB上限)时,用带keepalive属性的fetch降级 if (!requestQueued) { fetch('/api/user/logout', { method: 'POST', body: logoutParams, keepalive: true }); } });
兜底补充方案:visibilitychange 事件适配极端场景
部分极端场景下beforeunload不会触发,比如移动端将浏览器切后台后被系统回收进程、用户强制结束浏览器进程等,可以用visibilitychange事件做兜底:
document.addEventListener('visibilitychange', () => { // 页面切换为不可见状态时触发登出 if (document.visibilityState === 'hidden') { const logoutParams = new FormData(); logoutParams.append('user_token', localStorage.getItem('current_user_token')); navigator.sendBeacon('/api/user/logout', logoutParams); } // 可选:用户切回页面时调用会话续期接口恢复登录状态 if (document.visibilityState === 'visible') { fetch('/api/session/renew', { method: 'POST', credentials: 'include' }); } });
关键注意事项
- 不要在卸载事件中使用普通异步fetch/异步XHR:页面卸载进程启动后,所有异步请求会被直接中断,无法成功发送
- 不建议使用同步XHR作为实现方案:同步请求会阻塞页面卸载流程,用户需要等待请求完成才能关闭标签页,体验极差,且目前多数主流浏览器已经在页面卸载场景下禁用了同步XHR
- 没有方案可以100%覆盖所有关闭场景:设备断电、系统强制杀进程等极端情况无法触发浏览器事件,建议后端配合设置会话过期机制,长时间无操作后自动失效会话,弥补前端方案的覆盖缺口
- 单页应用路由跳转不要绑定该逻辑:仅页面真正卸载时需要触发,路由切换属于页面内逻辑,不需要触发登出
内容的提问来源于stack exchange,提问作者Aniket Deshpande
相关产品推荐
相关产品推荐

