O problema desta aproximação é que ficamos fazendo um monte de requisições ao servidor das quais a maioria é apenas para dizer “nenhuma novidade por aqui”
Uma forma contundentemente mais limpa e saudável é usar WebSocket. YeAPF inclui suporte para WebSocket desde o final de 2016. O problema com eles é que você precisa de disponibilizar um porto no seu servidor apenas para ele e utilizar um certificado para poder fazer https em lugar de http com o qual o projeto pode ficar inviabilizado. Insisto, porém, em dizer que é uma solução muitíssimo mais rica e -em certo sentido- potente do que a SSE.
Os SSE surgem como uma resposta ao gargalo situacional criado pelo exposto logo acima. Pense neles como um WebSocket simplificado. Ou seja, uma tomada ao qual seu aplicativo se conecta e por meio dela o servidor avisa quando há coisas para serem puxadas. Esse aviso gera um evento no cliente que já pode ser o dado a ser puxado ou uma indicação para utilizar outras tecnologias para puxar a informação.
Não é o escopo deste artigo ensinar SSE, mas pode dar uma olhada neste link da W3Schools e também neste outro da MDN.
O YeAPF permite a construção de aplicativos usando SSE de forma bem simples. Caso o SSE não funcione bem ou não esteja implementado (como no caso de Opera for Linux ou algumas versões de Mozilla for Windows) o YeAPF vai automaticamente cair para uma versão de polling que ao menos permitirá continuar com o uso do aplicativo de forma aceitável (é claro que não vai ser possível construir um jogo de ação online fazendo polling mas dá para o gasto em aplicativos comerciais)
O exemplo a seguir mostra a utilização do SSE no Javascript. Neste caso trata apenas da ‘recepção’ dos eventos que são gerados pelo servidor ou pelo próprio SSE.
/* inicializo um SSE indicando um grupo de trabalho */
mySSE = ycommSSEBase('agenda');
/*
adiciono alguns gestores de eventos ao SSE
o evento 'ready' é disparado pelo SSE e indica que ele está pronto para funcionar
o evento 'close' é disparado pelo SSE e indica o fechamento (correto ou não) do SSE
*/
mySSE.addEventListener(
"ready",
function(e) {
console.log("ready: "+e.gateway);
}
);
mySSE.addEventListener(
"close",
function(e) {
console.log("close");
}
);
/* 'marcar' é um evento criado pelo programador */
mySSE.addEventListener(
"marcar",
function(e) {
var dados = JSON.parse(e.data);
console.log("dados: "+e.data);
y$('registro').innerHTML+=e.data;
}
);
Com o exemplo anterior, recebemos as mensagens enviadas do servidor. Essas mensagens podem ser disparadas por outros eventos de outros clientes por exemplo ou do próprio servidor, ou na recepção de um e-mail… enfim a imaginação do programador é o limite.
Para simplificar as coisas, faremos com que o mesmo aplicativo envie certa informação ao servidor, o servidor a receba, a manipule e a envie de novo ao cliente que a receberá nesse evento ‘marcar’ que acabamos de inventar.
<script src='js/yloader.js'></script> <script src='js/exemplo_sse.js'></script> <button class="button" id="btnMarcar">Marcar</button> <div id="registro"></div>
HTML com um botao e uma div para o registro da atividade.
/* js/exemplo_sse.js */
contador = 0;
enviarEventoMarcar = function(e) {
contador++;
ycomm.invoke("meu_gestor", "xMarcar", { c: contador });
}
addOnLoadManager(
function() {
addEvent('btnMarcar', 'click', enviarEventoMarcar);
/* inclua aqui o código de inicialização do mySSE
* mostrado no inicio deste exemplo */
}
);
Javascript para criação do evento. Repare que estamos usando xMarcar em lugar de marcar para facilitar a leitura durante o aprendizado. Em produção deixamos os dois iguais para poder acompanhar melhor.
<?php
/* meu_gestor.php */
function qmeu_gestor($a)
{
/* retorno nulo */
$ret='';
/* publicamos as variáveis passadas como parâmetros no invoke
por exemplo, o 'c' que criamos do lado do cliente no javascript
aparece aqui como uma variável local */
extract(xq_extractValuesFromQuery());
/* analisamos o evento de entrada */
switch($a)
{
/* caso se trate do xMarcar ... */
case 'xMarcar':
/* mostrarei a data do servidor */
$ts = date('c');
/* mostrarei um valor aleatorio */
$v = random(1000,9999);
/* empacoto os dados.
'ts' e 'v' estou criando aqui ao passo que
'c' veio do javascript */
$data = array("c" => $c, "ts"=> $ts, "v" => $v);
/* envio para os clientes conectados (todos eles) */
SSE::broadcastMessage('marcar', json_encode($data));
/* indico ao cliente que o envio foi bem sucedido */
$ret = array('envio' => 'ok');
break;
}
/* retorno normal de um invoke */
xq_produceReturnLines($ret, true, 20);
}
?>
PHP para a recepção do evento do lado do servidor.
Bem, se tudo deu certo, seu aplicativo deve mostrar a data do servidor e um contador que vai mudando a cada vez que o botão é clicado.
Se isso está funcionando, abra um outro navegador de verdade (todos menos o IE) e veja o que acontece. Abra mais dois ou três. A cada clique do botão em um dos clientes, os outros devem ser informados. Há alguns navegadores em que o SSE está mal implementado ou com requisitos superiores. Nesse caso, o gateway não vai ser ‘SSE‘ no evento ‘ready’ e sim ‘Polling‘. Ele mesmo detectará se é melhor fazer invoke() ou crave(). Dependendo das necessidades do aplicativo você pode usar isso para impedir que o mesmo seja utilizado nesse navegador.
Se isso lhe fez feliz, coloque num servidor publico distante (se tiver um servidor na Ásia melhor….kkkk)
]]>