Ajax is a normal HTTP request, but it runs at background
, Ajax is to be more exact is a "way" of using the XmlHttpRequest
API asynchronously, but anyway the request is a normal HTTP request, it requests once it receives the response and closes the request, more details in:
The server-sent events ( SSE) is different , it's more similar to WebSocket , however other than WebSocket , SSE can work on a normal HTTP server, as PHP should know, asp.net-mvc and other web technologies run on the server side and only send you the response when you request / request, then when you do this:
var evtSource = new EventSource("api.php");
You'll be in a kind of persistent connection , meaning api.php
can stay in an infinite loop, never ending, instead of you get the response it's as if PHP sent you the response at the time it's wanted, for example:
date_default_timezone_set("America/Sao_Paulo");
header("Content-Type: text/event-stream\n\n");
$counter = rand(1, 10);
while (1) {
echo "event: ping\n";
$curDate = date(DATE_ISO8601);
echo 'data: ' . $curDate;
echo "\n\n";
$counter--;
if (!$counter) {
echo 'data: This is a message at time ' . $curDate . "\n\n";
$counter = rand(1, 10);
}
ob_end_flush();
flush();
sleep(1);
}
Every second is the PHP "who is going to send a request" (relatively speaking) to the client-side, and you will be observing with:
evtSource.onmessage = function(e) {
console.log(e.data); //Pega a resposta do PHP
}
SSE format
The sse has a somewhat standard format, first you need to pass the Content-Type: text/event-stream
on the headers, and then what would be equivalent to the body must contain these fields (not all at the same time, it depends a lot on what you want to do):
-
event :
If an event is specified in the window / tab that started SSE, the event will call an event added with addEventListener
to itself new EventSource
, if it does not have a named event the onmessage
p>
-
data
Send a string to onmessage
, if you need multiple lines it will be necessary to start with data:
, EventSource
will receive all concatenated lines, line breaks will be removed
-
id
It's used to identify the event, of course it can change, I think it's more to use to know who's calling what.
-
retry
Set the time to reconnect when trying to send an event, if the script on the server side is not in loop, EventSource
ends alone and tries again after the last time set in retry
(if set), otherwise I think it uses default time, apparently it also tries to connect again if it has problems with connection.
Support
Depending on the caniuse browsers that support SSE are:
- Chorme 6
- Firefox 6
- Safari 5
- Android 4.4 native browser
Note: Internet Explorer and Microsoft Edge do not support SSE, Edge is under construction,
Some BUGs or related support details:
-
CORS in EventSource
is only supported from Firefox 10+, Opera 12+, Chrome 26+, and Safari 7.0 +.
-
Until version 36 of Firefox there was a bug, perhaps there was a loss of connection EventSource
itself did not try to reconnect, despite what was said by caniuse it is possible to get around this used to property evtSource.readystate
to check which state:
- Returns
0
if you are still connecting
- Returns
1
if it is open
- Returns
2
if it is closed, that is, you can add setTimeout
to check it and if 2
yourself can try to reopen.
-
Until Firefox 52 there was no support for EventSource
on web / shared workers
-
-
-
Testing the SSE
MDN left an example in PHP: link , however I created a simpler example, if using PHP, create a script by calling chatbox.html
(not must be .php
, but it does not make any difference in this case) with this content:
<!DOCTYPE html>
<html>
<head></head>
<body>
<button id="close">Terminar conversa</button>
<div id="chatbox"></div>
<script type="text/javascript">
var btnClose = document.getElementById("close");
var chatbox = document.getElementById("chatbox");
var evtSource = new EventSource("chat.php");
evtSource.onmessage = function(e) {
var n = document.createElement("p");
n.innerHTML = "message: " + e.data;
chatbox.appendChild(n);
};
btnClose.onclick = function () {
evtSource.close(); //Finaliza a conexão do SSE
};
</script>
</body>
</html>
And then do not create a file with the name chat.php
in the same folder and add this content:
<?php
header('Content-Type: text/event-stream');
$canned = array(
'Oi?',
'Quer tc?',
'você é de onde?',
'Poderia me ajudar com uma duvida de JS?',
'já usou o stack overflow?',
'Vamos jogar um fut?'
);
$size = count($canned) - 1;
echo 'data: <strong>Você entrou na sala!</strong>';
echo "\n\n"; //Requer duas quebras de linha
//Loop "infinito"
while (1) {
//Pega uma "mensagem pronta" aleatória
$response = $canned[mt_rand(0, $size)];
echo 'data: ', htmlentities($response);
echo "\n\n"; //Requer duas quebras de linha
flush();
//Varia entre 1 e 4 segundos para que o PHP envia uma nova mensagem para o SSE
sleep(mt_rand(1, 4));
}
This script simulates a person sending messages to you, it's just to understand the behavior