为什么不能同时使用 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()
来实现此目的的位置。
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()
来实现此目的的位置。