Ajax is a normal HTTP request, but runs on background
, Ajax is to be more exact is a "way" to use the API XmlHttpRequest
asynchronously, but anyway the request is a normal HTTP request, it once requests the reply and closes the request, more details on:
The server-sent Events (SSE) is different, he’s over similar at the Websocket, however other than Websocket, SSE can work on a normal HTTP server, as you may know PHP, Asp.net-mvc and other web technologies run on server side and only send you the reply when you request/request, so when you do it:
var evtSource = new EventSource("api.php");
You’ll be in a kind of persistent connection, namely the api.php
can stay in an infinite loop, without ever ending, instead of you catch the answer is as if PHP sent you the answer at the time you want it, 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 will send a request" (relatively speaking) to the client-side, and you will be watching with:
evtSource.onmessage = function(e) {
console.log(e.data); //Pega a resposta do PHP
}
SSE format
The sse has a somewhat standard format, first it is necessary to pass the Content-Type: text/event-stream
in headers, and then what would be equivalent to the body should contain these fields (not all at the same time, it depends a lot on what you want to do):
Event:
If specified an event will be triggered in the window/tab that started SSE, the event will call an event added with addEventListener
to own new EventSource
, if you do not have a named event the onmessage
date
Send a "string" to the onmessage
, if you need multiple lines it will be necessary that all start with data:
, the EventSource
will receive all concactenated lines, line breaks will be removed
id
It is used to identify the event, of course it can change, I believe it is more for use to know who is calling what.
Retry
Sets the time to reconnect when trying to send an event, if the server-side script is not looped EventSource
finishes alone and tries again after the last time set in retry
(if set), otherwise I believe it uses the default time, apparently it also tries to connect again if you have problems with connection.
Support
According to the kennel the browsers that support SSE are:
- Chorme 6
- Firefox 6
- Safari 5
- Native Android Browser 4.4
Note: Internet Explorer and Microsoft Edge do not support SSE, Edge is under construction, may soon have support
Some Bugs or details about support reported:
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, there was a loss of connection itself EventSource
did not attempt to reconnect, despite what was said by kennel It is possible for you to circumvent it used property evtSource.readystate
to check the state:
- Returns
0
if you’re still connecting
- Returns
1
if it’s open
- Returns
2
if it is closed, that is, you can add a setTimeout
to check in and check out 2
you can even try to reopen.
Until Firefox 52 there was no support for EventSource
in web/Shared Workers
Eventually Antivirus software programs might block or cause some conflict (I’m not sure how it happens, if I find something about this I will edit the answer).
Testing the SSE
To MDN left an example in PHP: https://github.com/mdn/dom-examples/tree/master/server-sent-events, however I created a simpler example, if using PHP, create a script by calling chatbox.html
(doesn’t have to be .php
, but it makes no 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 in the same folder create a file with the name chat.php
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
Let’s play a Fut? only if it is now xD!
– gato
SSE is lighter than Ajax for the server then?
– Jefferson Quesado
The PHP script that runs on the server, it is automatically destroyed as soon as the connection is terminated? You would need to use the
connection_aborted ()
?– Don't Panic
@Jeffersonquesado This "lightweight" thing is very relative, I mean, the PHP script will stay open constantly, so it won’t need to be reinterpreted (php is not compiled), it helps the server, but it is something that can be quite relative, depends a lot on what you did in the back-end, so I didn’t cite the question of better or worse.
– Guilherme Nascimento
@Everson I will check and warn you.
– Guilherme Nascimento
@Guilhermenascimento I imagined that with SSE generates less traffic and less overhead due to http loads. I wasn’t talking about any particular backend. Overall, by your response, it seems to avoid even a good weight from an Ajax call
– Jefferson Quesado
@Jeffersonquesado yes basically this is what happens with persistent connections usually, decrease HTTP requests helps a lot, especially if it’s something really heavy on the back-end side, but if it’s a light thing, maybe it doesn’t feel much better, I mean there probably will be, but it will be so minimal that you won’t even feel, I will try to confirm the details, if the persistent connection can be shared with all tabs or the same script that is running send reply to all SSE then I believe you will have a significant gain. Maybe I’ll say something about Websocket, ajax and SSE
– Guilherme Nascimento