React页面刷新/关闭时API请求被取消的解决方案咨询
可行替代实现方案
问题根源
浏览器触发beforeunload事件时,不会等待异步请求完成就会启动页面卸载流程,直接导致你的API请求被中断取消。
方案1:使用navigator.sendBeacon()(推荐)
这是浏览器专为页面卸载场景设计的API,会在后台异步发送请求,浏览器会尽可能保证请求完成,不会被页面卸载打断,对用户体验无影响。
代码示例
useEffect(() => { const cleanup = () => { // 处理 deleteAgentLoginDetails 请求 const deleteForm = new FormData(); deleteForm.append('agentId', userId.toUpperCase()); navigator.sendBeacon('/api/delete-agent-login-details', deleteForm); // 处理 agentLogout 请求 const logoutForm = new FormData(); logoutForm.append('agentId', userId.toUpperCase()); navigator.sendBeacon('/api/agent-logout', logoutForm); }; window.addEventListener('beforeunload', cleanup); return () => { window.removeEventListener('beforeunload', cleanup); }; }, [userId]);
注意:
sendBeacon默认使用POST方法,支持FormData、Blob、字符串等数据格式。若你的API需要特定Content-Type,可将数据封装为Blob来指定。
方案2:使用fetch的keepalive选项
fetch API支持keepalive: true配置,开启后请求会在页面卸载后保持连接,直到请求完成。
代码示例
useEffect(() => { const cleanup = async () => { // 处理 deleteAgentLoginDetails 请求 await fetch(`/api/delete-agent-login-details?agentId=${userId.toUpperCase()}`, { method: 'DELETE', // 按你的API实际请求方法调整 keepalive: true }); // 处理 agentLogout 请求 await fetch(`/api/agent-logout?agentId=${userId.toUpperCase()}`, { method: 'POST', // 按你的API实际请求方法调整 keepalive: true }); }; window.addEventListener('beforeunload', cleanup); return () => { window.removeEventListener('beforeunload', cleanup); }; }, [userId]);
注意:
keepalive有请求大小限制(通常为64KB),若请求数据过大可能失败,这种情况优先选sendBeacon。
方案3:同步XMLHttpRequest(不推荐)
通过同步请求阻塞页面卸载,直到请求完成,但会导致页面卸载卡顿,严重影响用户体验,仅作为极端场景的备选。
代码示例
useEffect(() => { const cleanup = () => { // 处理 deleteAgentLoginDetails 请求 const xhr1 = new XMLHttpRequest(); xhr1.open('DELETE', `/api/delete-agent-login-details?agentId=${userId.toUpperCase()}`, false); // false 表示同步 xhr1.send(); // 处理 agentLogout 请求 const xhr2 = new XMLHttpRequest(); xhr2.open('POST', `/api/agent-logout?agentId=${userId.toUpperCase()}`, false); xhr2.send(); }; window.addEventListener('beforeunload', cleanup); return () => { window.removeEventListener('beforeunload', cleanup); }; }, [userId]);
内容的提问来源于stack exchange,提问作者Ketli Pakoda
相关产品推荐
相关产品推荐

