同时通过HTML表单与AJAX发送两个POST请求的跨浏览器问题
问题描述
我尝试向不同站点发送两个POST请求:一个通过表单action属性发送,另一个在onsubmit事件中使用AJAX(XMLHttpRequest)发送。代码在Chrome浏览器中可正常运行(先发送AJAX POST请求,再发送表单POST请求),但在Firefox中仅能发送表单action的POST请求,AJAX请求无法触发。
表单POST代码
<form name="form_log" method="POST" action="Site1.php" onsubmit="return validate(this);"> <input type="text" name="username"> <input type="password" name="password"> <input type="submit" name="Submit" value="Enter"> </form>
AJAX POST代码
function validate(){ if(document.form_log.username.value == ""){ alert('User name is empty'); return false; } if(document.form_log.password.value == ""){ alert('Password is empty'); return false; } else{ var user=document.getElementsByName('username')[0].value; var pass=document.getElementsByName('password')[0].value; var parameters=`username=${user}&password=${pass}&Submit=Enter`; var url = "http://Site2.php"; var xhttp = new XMLHttpRequest(); xhttp.open('POST',url,true); xhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xhttp.onreadystatechange = ()=>{ if(xhttp.DONE && xhttp.status == 200){ console.log("SENT!"); } } xhttp.send(parameters); } }
问题原因与解决办法
这是因为你使用了异步AJAX请求(xhttp.open的第三个参数为true),Firefox在表单触发页面跳转前,会直接终止当前页面的进程,导致未完成的异步AJAX请求被取消;而Chrome有特殊机制允许异步请求在页面卸载前完成。
解决方法1:改用同步AJAX请求
将xhttp.open('POST',url,true)改为xhttp.open('POST',url,false),让AJAX请求完成后再执行表单提交。但此方法会阻塞页面,影响用户体验,且现代浏览器对主线程同步请求有一定限制。
修改后的关键代码片段:
xhttp.open('POST',url,false); // 第三个参数改为false,启用同步请求
解决方法2:先阻止表单默认提交,AJAX完成后手动提交表单
这种方式更友好,不会阻塞页面:
- 让
validate函数默认返回false,阻止表单自动提交; - 在AJAX的
onreadystatechange回调中,请求完成后手动调用表单的submit()方法。
修改后的完整代码:
function validate(){ if(document.form_log.username.value == ""){ alert('User name is empty'); return false; } if(document.form_log.password.value == ""){ alert('Password is empty'); return false; } var user=document.getElementsByName('username')[0].value; var pass=document.getElementsByName('password')[0].value; // 用URLSearchParams处理参数,避免编码问题 var params = new URLSearchParams(); params.append('username', user); params.append('password', pass); params.append('Submit', 'Enter'); var url = "http://Site2.php"; var xhttp = new XMLHttpRequest(); xhttp.open('POST',url,true); xhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xhttp.onreadystatechange = ()=>{ if(xhttp.DONE){ console.log("AJAX请求完成"); // 手动提交表单 document.form_log.submit(); } } xhttp.send(params); // 阻止表单默认提交行为 return false; }
额外注意事项
- 如果
Site2.php与当前页面不同域,需确保目标服务器配置了CORS(跨域资源共享),否则AJAX请求会被浏览器拦截; - 避免直接用模板字符串拼接参数,容易出现编码错误,推荐使用
URLSearchParams处理参数。
内容的提问来源于stack exchange,提问作者OJR
相关产品推荐
相关产品推荐

