onclick事件中如何实现不等待前序完成的并行ajax调用
问题根因
连续请求串行执行的核心原因是PHP默认的Session文件锁机制,和前端ajax本身无关:
- jQuery的
$.ajax默认就是异步并行模式,只要没手动设置async: false,前端不会主动阻塞请求排队 - PHP默认采用文件存储Session,当请求处于Session开启状态时,会独占锁Session文件,同用户的后续请求必须等前一个请求执行结束释放锁后才能运行,这就是单次请求2秒、5次请求总耗时10秒的根本原因。
最小改动修复方案(保留原有ajax逻辑,实现并行)
1. 后端PHP代码调整(核心修复)
PHP提供session_write_close()方法,可以在完成Session读写操作后提前释放锁,无需等待整个脚本执行完毕。修改后的insertdata.php代码如下:
<?php // 如需读取Session内的用户信息等数据,先完成Session初始化和读操作 session_start(); // 示例:$uid = $_SESSION['user_id']; // 所有Session读写操作完成后,立刻释放Session文件锁,避免阻塞后续请求 session_write_close(); $userdata = $_POST["userdata"]; // 后续调用AWS API写入数据的慢逻辑(2-5秒耗时),不会再阻塞其他并行请求 // 调用API向AWS数据库写入数据 ?>
注意:调用
session_write_close()后无法再修改、写入Session数据,所有Session相关操作必须放在该方法调用前完成。
如果你的接口完全不需要用到Session,可以直接在代码开头关闭Session自动启动,从根源避免锁问题。
2. 前端代码校验修正
原有前端代码存在两个隐性问题,修正后即可正常发起并行请求:
<html> <head> <!-- 请确保页面提前引入jQuery依赖,避免$未定义报错 --> </head> <body> <button onclick="ajaxcall()">Call the function</button> </body> <script> // 提前定义需要传递的userdata变量,避免JS ReferenceError报错 const userdata = { /* 替换为实际业务要传输的数据 */ }; function ajaxcall() { $.ajax({ url: 'insertdata.php', data: { userdata: userdata }, type: 'POST', // async参数默认即为true,无需额外配置,严禁设置为false(同步模式会强制请求串行) success: function(response) { // 此处对接口返回的响应数据进行业务处理 }, error: function(xhr) { // 增加错误捕获,方便排查请求异常 console.error('请求异常', xhr); } }); } </script> </html>
完成以上两处修改后,连续点击触发的请求会自动并行执行,总耗时基本和单次请求耗时持平。
进阶优化方案
如果不需要同步等待AWS写入结果再给用户反馈,可以进一步优化,把用户请求和慢写入逻辑解耦,彻底消除等待时间:
1. 后端异步队列解耦
将原来的同步写入逻辑调整为异步队列模式:
- 接口接收到前端传递的userdata后,先做基础校验,将数据写入高速队列(如Redis队列、本地临时消息队列)
- 校验通过后立刻给前端返回成功响应,整个接口耗时可以控制在几十毫秒内
- 服务器后台运行常驻消费脚本,从队列中读取数据,按AWS接口的QPS限制批量写入数据库
这种模式下用户点击按钮后几乎瞬间得到反馈,完全不需要等待2-5秒的API调用耗时,同时可以避免并行请求过多打垮AWS接口。
2. 原生fetch替代jQuery ajax
如果不想依赖jQuery,可以使用浏览器原生的Fetch API实现异步请求,无额外依赖、性能更好:
// 替换原有$.ajax逻辑 async function ajaxcall() { try { const formData = new FormData(); formData.append('userdata', JSON.stringify(userdata)); const res = await fetch('insertdata.php', { method: 'POST', body: formData }); const response = await res.text(); // 此处对接口返回的响应数据进行业务处理 } catch (err) { console.error('请求异常', err); } }
注意事项
- 如果接口逻辑全程需要写入修改Session,建议将Session存储从默认文件切换为Redis、数据库等无锁介质,从根源解决Session阻塞问题
- 如果用户点击频率过高,建议前端增加简单的防抖/节流逻辑,或者给每次写入生成唯一请求ID做幂等校验,避免重复写入脏数据
- 并行请求数量不要过大,浏览器对同域名的并发请求数有默认限制(一般为6个),超过限制的请求还是会在浏览器端排队,高频写入场景优先用后端队列方案。
内容的提问来源于stack exchange,提问作者A. Chithrai
相关产品推荐
相关产品推荐

