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

PMH*_*PMH 4 javascript php ajax server-sent-events

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

“服务器发送事件”:它在随机时间向控制台发送文本

如果我只使用 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);
});
Run Code Online (Sandbox Code Playgroud)

服务器

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';
}
Run Code Online (Sandbox Code Playgroud)

Dar*_*ook 6

您的 php 脚本对于 SSE 是正确的:

  • 它发送内容类型:文本/事件流
  • 这是一个无限循环,不断向客户端发送数据

另一方面,当你使用$.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);
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,请注意 PHP 会话处理,因为 PHP 会在脚本的整个生命周期内锁定会话。当您的 SSE 脚本永远运行时,这将停止任何其他 PHP 脚本的运行。

因此,如果您使用会话,但还计划在 SSE 脚本运行的同时进行 ajax 调用,请让您的 SSE 脚本与其会话断开连接。我已经显示,注释掉,上面你可以放一个session_write_close()来实现这一点。