You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置async为true的jQuery Ajax请求致Web应用卡顿直至数据返回

问题:异步Ajax请求为何导致整个Web应用卡顿?

我正在维护一个别人开发的PHP Web应用,执行下面这段jQuery Ajax请求:

$.ajax({ 
  type: 'POST', 
  url: "/potato/ajax.php?module=test_module", 
  dataType: 'json', 
  async: true, 
  data: { start_ts: that.start_date, stop_ts: that.end_date, submitted: true }, 
  beforeSend: function() { 
    console.log('Start: ' + new Date().toLocaleString()); 
    // Show Chart Loading
    that.qwChart.showLoading({ 
      color: '#00b0f0', 
      text: that.qwChartProgress 
    }); 
    // If data div isn't displayed
    if (!that.dataDisplayed) { 
      // Show divs loading
      that.showMainDiv(); 
    } else { 
      that.$qwTbody.slideUp('fast'); 
      that.$qwTbody.html(''); 
    } 
  }, 
  complete: function(){}, 
  success: function(result){ 
    console.log('End: ' + new Date().toLocaleString()); 
    // Clear timer
    clearInterval(timer); 
    // Set progressbar to 100%
    that.setProgressBarTo100(); 
    // Show Download Button
    that.downloadBtn.style.display = 'inline-block'; 
    // Insert Chart Data
    that.insertChartData(result); 
    // Insert Table Data
    that.insertTableData(result); 
  } 
});

按道理异步请求不该阻塞应用,但现在的情况是:提交Ajax请求后,刷新页面或并行打开应用内其他页面时,页面会白屏加载,直到Ajax请求返回数据后才正常显示。我特意手动设置了async: true确认,但问题依旧。这是服务端的问题吗?该怎么调试?

后端PHP处理代码如下:

<?php 
require_once("/www/common/api/db.php"); 
if (!empty($_POST['submitted'])) { 
    // error_reporting(-1); 
    // Users Array: 
    $users = get_qw_data($start_ts_to_date, $stop_ts_to_date); 
    // Summary Array: 
    $summary = get_qw_summary($users); 
    // QW Score Array: 
    $qws = get_qw_score($users); 
    // Generate CSV Report files 
    /* Remove old:*/ 
    if (!is_file_dir_exist($customer)) create_qw_directory($customer); 
    /* Report #1: */ 
    users_apps_google_macros_ma($users['users'], $customer); 
    /* Report #2: */ 
    usage_and_qw_summary($summary, $customer); 
    /* Report #3: */ 
    qw_score($qws, $customer); 
    /* Zip Files: */ 
    zip_qw_files($customer); 
    echo json_encode($qws); 
} 

分析与解决方案

兄弟,我太懂你这种困惑了——明明设了异步,怎么整个应用还是卡得像没开异步一样?答案几乎肯定在服务端的PHP会话锁上,这是PHP开发里非常容易踩的坑!

为什么会卡顿?

你说的“刷新页面/打开其他页面白屏”,本质不是前端异步请求的问题,而是PHP的session机制导致的:

  • 默认情况下,PHP当一个请求启动会话(比如用session_start(),或者框架自动启动)时,会锁住当前用户的session文件,防止多个请求同时修改session数据导致冲突。
  • 这个锁会一直持有,直到请求完全结束(脚本执行完毕,或者主动调用session_write_close()释放锁)。
  • 你的Ajax请求触发了后端的PHP脚本,这个脚本里大概率启动了会话(比如db.php里包含了会话初始化逻辑),而且脚本执行时间很长——你看后端代码里要生成多个CSV、压缩文件,这些都是耗时操作!
  • 这时候,同一个用户的其他请求(刷新页面、打开其他页面)都会因为等待session锁被释放而阻塞,表现出来就是页面白屏,直到Ajax请求的脚本执行完、锁释放,其他请求才能继续。

怎么调试验证?

  • 确认会话锁的存在:
    在后端PHP脚本的开头和关键位置添加日志,记录session_id()和当前时间,同时在另一个页面(比如首页)也添加同样的日志,然后同时触发Ajax请求和刷新首页,看首页的日志是不是在Ajax请求完成后才出现。也可以直接查看服务器上的session文件存储目录(通常是/var/lib/php/session/),用lsof命令查看哪个进程在占用对应session文件。
  • 验证脚本执行时间:
    在后端脚本开头加$start_time = microtime(true);,结尾加error_log("Script execution time: " . (microtime(true) - $start_time) . "s");,看看整个脚本跑多久——如果超过几秒,那肯定会导致明显卡顿。

解决办法

1. 尽早释放会话锁(最有效)

如果你的Ajax请求不需要修改session数据,只是读取或者根本不用session,那在脚本开头处理完session相关逻辑后,立刻调用session_write_close()释放锁:

<?php 
require_once("/www/common/api/db.php"); 
// 假设db.php里已经启动了session,现在立刻释放锁
session_write_close();

if (!empty($_POST['submitted'])) { 
    // 后面的耗时操作都不会持有session锁了
    $users = get_qw_data($start_ts_to_date, $stop_ts_to_date); 
    $summary = get_qw_summary($users); 
    $qws = get_qw_score($users); 
    // ... 剩下的文件生成、压缩逻辑
    echo json_encode($qws); 
} 

这样后续的耗时操作就不会占用session锁,用户的其他请求可以正常处理,不会被阻塞。

2. 优化后端耗时操作

你的脚本里生成多个CSV、压缩文件都是IO密集型操作,可以优化:

  • 把这些耗时操作放到异步任务队列里(比如用Redis队列+Worker进程),Ajax请求只触发任务,立刻返回结果,然后前端轮询或者用WebSocket通知任务完成。
  • 优化文件生成和压缩的代码,比如用更高效的函数,避免不必要的IO操作。

3. 检查其他阻塞因素

  • 看看后端脚本有没有执行长时间的数据库查询,比如get_qw_data()是不是拉取了大量数据,没有加索引?可以用EXPLAIN分析查询语句。
  • 服务器资源是不是不够?比如CPU、内存被占满,导致所有请求都变慢——可以用top或htop命令查看服务器监控数据。

内容的提问来源于stack exchange,提问作者Imnotapotato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:01:42