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

使用EventSource时客户端JS被阻塞的问题求助

问题分析与解决建议

你的问题核心是SSE(Server-Sent Events)长连接阻塞了同域名下的其他AJAX请求,根源在于PHP端的SSE脚本没有正确实现分块传输编码,导致浏览器的并发连接槽位被长期占用,无法处理其他请求。以下是具体解决步骤:


1. 修正PHP SSE脚本的核心逻辑

必须确保SSE脚本正确发送响应头、定期输出心跳包并强制刷新缓冲区,让浏览器知道连接处于活跃状态但不会占用请求槽位。

修改newmessage2.php代码如下:

<?php
// 设置SSE必备响应头
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no'); // 禁用Nginx等代理的缓冲,确保实时输出

// 关闭PHP输出缓冲,确保数据立即发送
if (ob_get_level() > 0) {
    ob_end_flush();
}
flush();

// 循环监听新消息,同时定期发送心跳
while (true) {
    // 业务逻辑:检查是否有新的呼叫消息
    $newCall = getNewCallData(); // 替换为你的实际查询逻辑

    if ($newCall) {
        // 发送NewCall事件
        echo "event: NewCall\n";
        echo "data: " . json_encode($newCall) . "\n\n";
        flush();
    }

    // 发送心跳包(浏览器会自动忽略以":"开头的注释行)
    echo ": ping\n\n";
    flush();

    // 休眠5秒,避免CPU占用过高
    sleep(5);
}

// 示例业务函数:模拟获取新呼叫数据
function getNewCallData() {
    // 这里替换为你的实际逻辑,比如查询数据库/缓存
    return rand(0, 10) > 7 ? ['id' => uniqid(), 'content' => '新呼叫通知'] : null;
}

2. 客户端代码补充(可选但建议)

原JS代码无需大改,可添加错误监听确保SSE连接异常时自动重连:

var sourceCallUpdater = new EventSource("./js/newmessage2.php");

sourceCallUpdater.addEventListener('NewCall', (e) => {
    // 处理新消息的逻辑
    const callData = JSON.parse(e.data);
    console.log('收到新呼叫:', callData);
    // 这里写更新页面的代码
});

// 监听SSE连接错误,确保异常时自动重连
sourceCallUpdater.addEventListener('error', (e) => {
    if (e.readyState === EventSource.CLOSED) {
        console.log('SSE连接断开,浏览器将自动重连');
    } else {
        console.error('SSE连接出错:', e);
    }
});

3. 关键原理说明

浏览器对同一域名的HTTP/1.1并发连接数默认限制为6个,若SSE脚本未正确分块输出,连接会一直处于"pending"状态,占用1个连接槽位。当你调用GotoPage发起AJAX请求时,会被排队等待槽位释放,直到SSE连接发送数据或断开。

通过定期发送心跳包并强制刷新缓冲区,浏览器会确认连接活跃但不会阻塞其他请求,同时避免连接因超时被断开。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:30:00