• 如何在页面关闭时优雅地发送API请求
  • 发布于 2个月前
  • 297 热度
    0 评论
日常开发中,我们经常需要在用户离开页面时,确保某些关键数据能够及时同步到服务器,比如用户的行为日志、表单的提交结果等。这篇文章将带你了解如何在页面关闭时优雅地发送API请求,确保数据正确地发送。

场景
想象一下,用户在填写一个重要的表单,突然浏览器崩溃或者用户不小心关闭了页面。这时,如果表单数据没有被保存,将会带来极大的不便。为了避免这种情况,我们需要在页面关闭时执行一个API请求,将数据发送到服务器。

浏览器事件监听
在浏览器中,我们可以使用beforeunload事件来监听窗口关闭前的事件。但是,这个事件并不总是可靠的,因为它可能会被浏览器的弹出拦截器阻止。因此,我们还需要考虑使用visibilitychange事件,它在页面从可见变为隐藏时触发,这包括了页面关闭和刷新的情况。
// 使用beforeunload事件
window.addEventListener('beforeunload', (event) => {
    // 在这里执行API请求
});
 // 堆代码 duidaima.com
// 使用visibilitychange事件
document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'hidden') {
        // 页面不再可见,执行API请求
    }
});
发送API请求的方法
有几种方法可以在页面关闭时发送API请求,包括传统的XMLHttpRequest、fetch API以及Navigator.sendBeacon方法。

- XMLHttpRequest
XMLHttpRequest是最早的API请求方法,但它在页面关闭时可能会被取消。
const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/data', true);
xhr.send(JSON.stringify(data));
- Fetch 使用 keepalive
fetch API提供了一个keepalive选项,即使页面关闭,请求也会继续执行。
fetch('/api/data', {
    method: 'POST',
    body: JSON.stringify(data),
    keepalive: true
});
- Navigator.sendBeacon
Navigator.sendBeacon是一个现代的、轻量级的方法,它允许在不阻塞页面卸载的情况下发送数据。
navigator.sendBeacon('/api/data', JSON.stringify(data));
通过 HTTP POST 请求方式 异步 发送数据,同时不会延迟页面的卸载或影响下一导航的载入性能;
支持跨域,但不支持自定义 headers 请求头,这意味着:如果用户信息 Access-Token 是作为请求头信息传递,需要后台接口支持 url querystring 参数传递解析。

考虑其兼容性。


最佳实践
在选择发送API请求的方法时,我们需要考虑兼容性、数据大小和服务器响应。Navigator.sendBeacon是一个不错的选择,因为它不会影响页面的卸载性能,但需要注意的是,它不支持自定义请求头,且数据大小有限制。fetch API的keepalive选项也是一个可靠的选择,但同样需要注意数据大小的限制。

在实际应用中,我们可能需要根据具体场景和需求,选择最合适的方法。为了提高成功率,我们可以结合使用多种方法。例如,首先尝试使用Navigator.sendBeacon,如果不支持,再尝试fetch API。

思考
在框架的生命周期,如 React useEffect 与 Vue beforeDestroy可以实现页面关闭时发送 HTTP 请求记录数据吗?

答案是:不可以。

beforeDestroy 是在组件被销毁时调用的,这通常发生在组件从DOM中移除的时候,而不是在浏览器窗口或标签页关闭时。页面关闭时,整个Vue实例的生命周期都会结束,包括所有组件。React 的 useEffect同理!
用户评论