
本文解析为何单个耗时 ajax 请求会导致同一 chrome 会话中整个网站“卡死”,并提供基于 promise 的非阻塞式调用方案,确保页面交互持续可用。
本文解析为何单个耗时 ajax 请求会导致同一 chrome 会话中整个网站“卡死”,并提供基于 promise 的非阻塞式调用方案,确保页面交互持续可用。
这种现象并非 AJAX 本身“阻塞了浏览器”,而是由浏览器对同一域名下并发连接数的限制与PHP 会话(session)默认阻塞机制共同导致的典型问题。
当你在 controller.php 中执行耗时的 cURL 操作(15–20 秒)时,若该脚本开启了 PHP session(例如通过 session_start()),PHP 默认会对 session 文件加独占写锁(exclusive file lock)。这意味着:只要该请求未结束,同一用户(共享 session ID)的其他请求将排队等待锁释放——即使它们是独立的 AJAX 调用、资源加载或页面跳转。而 Chrome 对同一域名默认最多维持 6 个并发连接(HTTP/1.1),且所有同源请求共享 session 上下文,因此你在当前标签页发起新请求(如刷新、导航、其他 AJAX)时,会因 session 锁被占用而挂起,表现为“整个网站变白/无响应”,直到长请求完成。
⚠️ 注意:此问题仅影响同一浏览器会话(即相同 Cookie/session ID)下的请求,因此其他设备、隐身窗口或不同账号访问不受影响——这正是你观察到“仅当前 Chrome 会话卡顿”的根本原因。
✅ 正确解法:解除 session 阻塞 + 规范异步处理
关键不在改写 AJAX 语法($.ajax 本就是异步的),而在于后端主动释放 session 锁,并配合前端清晰的异步控制流:
1. 后端优化(PHP):及时关闭 session
在 controller.php 开头,开启 session 后立即调用 session_write_close(),释放锁,允许其他请求并行执行:
<?php session_start();
// ✅ 立即释放 session 锁,避免阻塞其他请求
session_write_close();
$action = $_GET['action'] ?? '';
if ($action === 'loadPageContent') {
// 执行耗时 cURL 逻辑(此时无 session 锁)
$result = performHeavyCurlOperation();
header('Content-Type: application/json');
echo json_encode([
'status' => !empty($result),
'htmlDatas' => $result ?? '',
'date_scrapping' => date('c')
]);
}
? 提示:若需在 cURL 后写入 session 数据,请在最后重新调用 session_start() 并写入,但务必确保写入操作极轻量。
2. 前端增强:使用 Promise 封装,提升可维护性与错误隔离
虽然原生 $.ajax 已是异步,但封装为 Promise 可更好配合 async/await、实现链式调用、避免回调地狱,并明确区分成功/失败路径:
function ajaxCall() {
return new Promise((resolve) => {
$.ajax({
url: '/controller.php',
type: 'GET',
dataType: 'json',
data: { action: 'loadPageContent' },
success: function (retour) {
localStorage.removeItem('myhtml');
if (retour.status && retour.htmlDatas) {
storedDatas.posts = retour.htmlDatas;
storedDatas.date_scrapping = retour.date_scrapping;
localStorage.setItem('myhtml', JSON.stringify(storedDatas));
$('#container').html(retour.htmlDatas);
resolve(true); // 显式表示成功
} else {
alert('数据加载失败:返回格式异常');
resolve(false);
}
},
error: function (xhr, status, error) {
console.error('AJAX 请求失败', { xhr, status, error });
alert(`请求出错:${status}`);
resolve(false);
}
});
});
}
// 使用示例:支持 await,便于组合多个异步操作
async function runCodes() {
// ✅ 此处不会阻塞 UI,其他交互照常运行
const success = await ajaxCall();
if (success) {
console.log('内容加载完成');
} else {
console.warn('加载失败,可触发重试或降级逻辑');
}
// ✅ 其他 JS 代码可立即执行,无需等待
updateUIIndicators();
}
3. 进阶建议(强烈推荐)
- 启用 HTTP/2:减少连接竞争,提升并发能力;
- 使用 Web Workers 处理纯前端密集型任务(非本例主因,但可补充体验);
- 添加加载态反馈:如禁用按钮、显示 spinner,提升用户感知;
- 设置超时与重试:防止无限等待,例如在 $.ajax 中添加 timeout: 30000。
总结:AJAX “卡死网站”本质是服务端 session 锁引发的串行化瓶颈,而非前端异步失效。修复核心在于 session_write_close() + Promise 封装 + 清晰的状态管理。遵循此模式,即可在保持代码简洁的同时,彻底消除长请求对用户体验的负面影响。










