多请求场景下Ajax状态Pending问题:jQuery进度监听器实现故障修复问询
问题根源
- 核心原因是PHP默认的会话锁定机制:当同一个用户的多个请求同时到达时,PHP会给第一个请求(也就是
script.php)加上session文件锁,后续所有同用户的请求(包括所有checkprogress.php请求)都会进入排队状态,直到script.php执行完成释放锁,所以才会出现所有进度查询请求都pending到最后才一次性返回的情况。 - 次要原因可能是文件权限不足、服务端输出缓冲未关闭导致进度值不能及时返回。
修复方案
步骤1:修改两个业务脚本,关闭会话锁和输出缓冲
修改后的checkprogress.php
<?php // 关闭会话锁,释放请求阻塞 session_write_close(); // 关闭PHP自带输出缓冲 if (ob_get_level()) ob_end_clean(); // Nginx环境可选加下一行,关闭代理缓冲 // header('X-Accel-Buffering: no'); $file = "progress.txt"; // 兼容文件不存在的场景,默认返回0 if (!file_exists($file)) { echo 0; } else { $data = file_get_contents($file); echo $data; } exit; ?>
修改后的script.php
<?php // 同样关闭会话锁,避免阻塞后续进度查询请求 session_write_close(); $file = "progress.txt"; // 初始化进度为0 file_put_contents($file, 0); for($i = 1; $i<= 10; $i++){ sleep(1); file_put_contents($file, ($i * 10)); } echo "执行完成"; // 任务执行完成后可选删除进度文件 // unlink($file); ?>
步骤2:确认目录权限
确保脚本运行目录有可写权限,保证script.php可以正常创建、写入progress.txt文件,Linux环境下可以临时给当前目录设置755权限测试。
步骤3:可选优化前端代码(非必须,避免全局变量污染)
给xhr、timer、xhr2变量加上let声明,避免变成全局变量引发异常:
function begin(event){ let xhr = new XMLHttpRequest(); let timer; // 其余原有逻辑保持不变 } function checkProgress(event){ let xhr2 = new XMLHttpRequest(); // 其余原有逻辑保持不变 }
验证效果
修改完成后重启PHP服务,清空浏览器缓存重新测试,即可看到进度条每秒上涨10%,10秒后弹出执行完成提示。
内容的提问来源于stack exchange,提问作者Zack Snyder
相关产品推荐
相关产品推荐

