JavaScript如何在浏览器关闭时正确保存数据到MySQL数据库?
问题根因
onunload事件触发时,浏览器会直接终止页面所有待执行的异步请求、销毁页面进程,你使用的常规异步AJAX请求还没完成发送就被中断了。断点调试时进程被临时暂停,才有足够时间走完请求流程,所以只有调试时能保存成功。
可行解决方案
方案1:使用navigator.sendBeacon()(推荐)
这是W3C专门为页面卸载阶段发送数据设计的API,浏览器会在后台异步完成请求,不阻塞页面关闭流程,且会尽可能保证请求发送成功。
修改后的代码如下:
<!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> </head> <body> <h1>Testing data save on close event</h1> </body> </html> <script> window.onunload = function(e) { console.log("The Window is closing!"); saveDataOnClose(); }; function saveDataOnClose(){ const url = URL+"savedata.php"; const client = [{firstName: 'John', lastName: 'doe', EmailAddress: 'jhon@gmail.com'}]; const jObj = JSON.stringify(client); // 构造FormData方便PHP直接通过$_POST接收参数 const formData = new FormData(); formData.append('Client', jObj); // 发送beacon请求 navigator.sendBeacon(url, formData); } </script>
后端PHP接口无需修改,直接和之前一样通过$_POST['Client']即可拿到数据。
方案2:使用带keepalive参数的Fetch API
和sendBeacon逻辑类似,通过keepalive参数告知浏览器页面关闭后也要继续完成请求:
function saveDataOnClose(){ const url = URL + "savedata.php"; const client = [{firstName: 'John', lastName: 'doe', EmailAddress: 'jhon@gmail.com'}]; const formData = new FormData(); formData.append('Client', JSON.stringify(client)); fetch(url, { method: 'POST', body: formData, keepalive: true }); }
注意事项
- 不要使用同步AJAX(给
$.ajax加async: false参数),目前主流浏览器已经在unload、beforeunload事件中禁用了同步XHR请求,添加后也不会生效,还会触发控制台警告。 sendBeacon和带keepalive的fetch都有单请求数据大小限制,一般为64KB,存储常规用户操作数据完全够用,超出限制请求会发送失败。- 页面卸载后请求的成功/失败回调都不会执行,不要依赖回调做后续逻辑,后端接口要做好幂等处理,避免重复提交产生脏数据。
- 如果需要给用户弹出是否保存的确认提示,可以搭配
onbeforeunload事件使用,用户确认关闭后再触发数据保存逻辑。
内容的提问来源于stack exchange,提问作者Sidath
相关产品推荐
相关产品推荐

