为什么不能同时使用ajax和服务器发送事件?

4

Ajax: 每次点击时,会发送一个ajax请求,控制台将显示服务器发送的文本。

"server sent event":它会在随机时间向控制台发送文本。

如果我只使用Ajax,我可以从服务器收到数据。但是如果我同时使用这两种方法,我不能够从Ajax请求的响应中接收到来自服务器的数据,但仍然会接收到来自“服务器发送事件”的消息。我甚至没有收到Ajax请求失败的消息。有人能解释一下吗?

客户端

var evtSource = new EventSource("config/addRemoveEvent.php");
evtSource.onmessage = function(e) {
  //var newElement = document.createElement("li");
  console.log("listening: "+ e.data);
  //newElement.innerHTML = "message: " + e.data;
  //eventList.appendChild(newElement);
}   

var data = {
    'action':'Initiate brief calendar', 
    'selectedMonth': month, 
    'selectedYear': year
};

var $request = $.ajax({
    type: "GET",
    dataType: "text",
    url: "config/addRemoveEvent.php",
    data: data,
    beforeSend: function(){
        console.log('start sending request');

    }
});

$request.fail(function(){
    console.log('fail');
}); 
$request.done(function(data){
    // change bg color of the cells that contain events;
    console.log(data);
});

服务器

header("Content-Type: text/event-stream\n\n");
date_default_timezone_set("America/New_York");

while (1) {

  if (!$counter) {
    echo 'data: This is a message at time ' . $curDate . "\n\n";
    $counter = rand(1, 3);
  }

  ob_flush();
  flush();
  sleep($counter);
}

// return the date has event in a given month 
if($_GET['action'] == "Initiate brief calendar"){
    echo 'hello';
}

我刚刚更新了代码,因为我忘记包括服务器发送事件的代码。 - PMH
1个回答

6
您的 PHP 脚本对于 SSE 是正确的:
  • 它发送 Content-Type: text/event-stream
  • 它是一个无限循环,以便向客户端发送数据
另一方面,当您使用 $.ajax 时,它期望一个服务器脚本将发送一堆数据并关闭连接。
使用 PHP 脚本同时执行这两个操作是可能的,但代码质量较差:最好有两个脚本、两个 URL。
实际上,您的代码几乎完成了,只需先处理特殊操作,然后退出即可。
date_default_timezone_set("America/New_York");

// return the date has event in a given month 
if($_GET['action'] == "Initiate brief calendar"){
    echo 'hello';
    exit;
}

//session_write_close();  //See below

header("Content-Type: text/event-stream\n\n");
while (1) {

  if (!$counter) {
    echo 'data: This is a message at time ' . $curDate . "\n\n";
    $counter = rand(1, 3);
  }

  ob_flush();
  flush();
  sleep($counter);
}

顺便提一下,要小心处理PHP会话,因为PHP会在脚本的生命周期内锁定会话。由于你的SSE脚本永远运行,这将阻止其他PHP脚本的运行。

所以如果你使用会话,但同时计划在SSE脚本运行的同时进行ajax调用,请让SSE脚本从会话中断开连接。我已经在上面的注释中展示了一个session_write_close(),你可以将其放置在相应位置来实现此功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接