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

如何让XMLHttpRequest发起的AJAX请求后台执行邮件发送不阻塞后续请求

问题核心原因

你的阻塞问题来自两个层面:

  1. PHP同步执行逻辑:chat.php 中数据库插入完成后需要同步等待mailSender()执行完毕才会返回HTTP响应,前端第一个AJAX的onload回调会延迟触发
  2. PHP会话锁:默认情况下同一用户的多个请求会共享会话锁,chat.php未执行完成前,同用户的get-chat.php请求会被阻塞排队,就算拉取频率是500ms也不会及时执行

最优轻量解决方案:服务端提前返回响应,后台异步发邮件

仅需要修改chat.php的代码,不用改前端逻辑,改造成本最低:

$stmt = $pdo->prepare("INSERT INTO messages(incoming_msg_id, outgoing_msg_id, msg)VALUES(:imsg, :omsg, :msg)");
$stmt->bindValue(':imsg', $imsg);
$stmt->bindValue(':omsg', sessionUser());
$stmt->bindValue(':msg', encrypt($chatMsg, ENCRYPTION_KEY));
$stmt->execute();

if($stmt){
    // 清空之前的输出缓冲区
    ob_end_clean();
    // 返回200成功状态
    http_response_code(200);
    // 可选:如果前端需要返回业务数据可以在这里输出,比如echo json_encode(['code'=>0,'msg'=>'success']);
    // 计算响应内容长度,告知浏览器接收完对应长度内容后直接结束请求
    header("Content-Length: " . ob_get_length());
    header("Connection: close");
    // 将缓冲区内容全部推送给浏览器
    ob_end_flush();
    flush();
    // 提前关闭会话,解除会话锁,让后续的get-chat.php请求可以立即执行
    session_write_close();

    // 后续邮件逻辑放到响应返回后执行,完全不阻塞前端
    $sub = 'MAIL SUBJECT GOES HERE';
    $message = 'MAIL CONTENT GOES HERE';
    mailSender($sub, $message, "abc@gmail.com");
}

改完后你前端的插入消息AJAX会立刻收到响应,输入框清空、滚动到底的逻辑马上执行,同时500ms一次的拉取请求也能立刻读取到刚插入的新消息,邮件在服务端后台异步发送不影响用户操作。

生产环境高可用方案:引入任务队列

如果你的站点流量较大,需要保证邮件发送成功率、支持失败重试,建议用任务队列实现:

  • 新增邮件任务表/Redis队列,chat.php插入消息成功后,将邮件的标题、内容、收件人等参数写入队列,立即返回响应给前端
  • 额外部署后台常驻进程/定时脚本,单独消费队列里的邮件任务执行发送逻辑
    这个方案完全隔离了邮件发送和主业务流程,稳定性更高,适合正式线上环境使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 01:15:02