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

如何检测浏览器页面退出/变更操作并触发finishTheTest()函数?

页面离开时自动触发测试状态保存的实现方案

问题背景

开发测试应用时,需要在以下所有场景触发finishTheTest()函数(用于保存答案、测试时长等状态):

  • 用户刷新页面
  • 用户回退页面
  • 用户关闭标签页/浏览器窗口
  • 用户跳转到其他URL
  • 任何导致页面卸载的极端情况(如电脑关机、断网等)

此前尝试的代码仅返回提示语,未实现状态保存逻辑,且未考虑现代浏览器的行为限制:

function UnLoadWindow() {
    return 'We strongly recommends NOT closing this window yet.'
}

window.onbeforeunload = UnLoadWindow;

解决方案

1. 正确利用beforeunload事件触发保存逻辑

beforeunload事件会在页面即将卸载时触发,覆盖绝大多数页面离开场景。在事件处理函数中直接调用finishTheTest(),并返回提示语以兼容不同浏览器的确认弹窗逻辑:

window.addEventListener('beforeunload', function(event) {
    // 触发测试状态保存
    finishTheTest();
    
    // 部分浏览器需要返回非空字符串才能触发确认提示(自定义内容可能被浏览器替换为默认文案)
    event.returnValue = '测试状态未保存,确定离开?';
    return '测试状态未保存,确定离开?';
});

2. 处理异步保存的可靠性问题

如果finishTheTest()涉及向服务器发送数据的异步操作,普通的fetch/XMLHttpRequest可能被浏览器中断,需使用navigator.sendBeaconAPI——它能保证浏览器在页面卸载前完成数据发送:

function finishTheTest() {
    // 收集测试数据(示例)
    const testData = {
        answers: getUserAnswers(),
        duration: getTestDuration(),
        userId: getCurrentUserId()
    };

    // 优先使用sendBeacon发送数据
    if (navigator.sendBeacon) {
        const formData = new FormData();
        Object.entries(testData).forEach(([key, value]) => {
            formData.append(key, JSON.stringify(value));
        });
        // 发送到后端接口
        navigator.sendBeacon('/api/save-test-state', formData);
    } else {
        // 兼容旧浏览器:使用同步XMLHttpRequest(仅作为 fallback,不推荐)
        const xhr = new XMLHttpRequest();
        xhr.open('POST', '/api/save-test-state', false);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.send(JSON.stringify(testData));
    }
}

3. 极端场景的兜底处理

对于断网、电脑关机等无法即时发送数据的场景,建议先将测试状态保存到本地存储(如localStorage),定期同步到服务器,或在用户下次打开页面时自动上传:

// 定期保存到本地存储(示例:每30秒)
setInterval(() => {
    const testData = {
        answers: getUserAnswers(),
        duration: getTestDuration(),
        userId: getCurrentUserId()
    };
    localStorage.setItem('unsavedTestState', JSON.stringify(testData));
}, 30000);

// 页面加载时检查本地存储,同步未上传的数据
window.addEventListener('load', function() {
    const savedState = localStorage.getItem('unsavedTestState');
    if (savedState) {
        const testData = JSON.parse(savedState);
        // 调用保存逻辑上传数据
        finishTheTest(testData);
        // 上传成功后清除本地存储
        localStorage.removeItem('unsavedTestState');
    }
});

注意事项

  • beforeunload事件中避免执行耗时操作,浏览器会限制该事件的执行时间。
  • 部分浏览器会忽略自定义的提示语,仅显示默认弹窗内容,但不影响finishTheTest()的执行。
  • 同步XMLHttpRequest会阻塞页面卸载,仅作为sendBeacon的兜底方案,优先使用sendBeacon。

内容的提问来源于stack exchange,提问作者Umer Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:55:21