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

Why cannot use both ajax and server sent event?

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

"server sent event": 它随机发送文本到控制台

如果我只使用 ajax,我从服务器接收数据。但是如果我同时使用这两种方法,我没有从服务器收到响应 ajax 请求的数据,但仍然收到响应 "server sent event" 的消息。我什至没有收到来自 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';
}

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

  • 它发送内容类型: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() 来实现此目的的位置。