O XMLHttpRequest ou XHR, mudou tudo. Graças a essa API, o client-side pode transferir dados via Javascript. Ele inseriu o \\\”D\\\” na frente do HTML e nos permitiu obter assincronismo em nossas aplicações web. Antes dele, uma página precisava ser recarregada para enviar ou receber dados do servidor. Apesar de estar presente nos browsers desde o Internet Explorer 5, o XHR ainda é essencial para desenvolvermos aplicações web ricas e pode também ser usado – apesar de existir, hoje, tecnologias como websocket – para aplicações de tempo real.
XHR nos fornece uma maneira eficiente de sincronizar atualizações entre cliente e servidor. Quando necessário, uma requisição XHR envia dados para o servidor. O problema é o inverso.
Notificações em tempo real
O HTTP não fornece nenhuma maneira de o servidor iniciar uma nova conexão com o cliente. Para receber notificações, o cliente deve fazer polling, ou seja, fazer requisições periódicas ao servidor para pegar atualizações. Uma outra forma seria utilizar streaming, mas o suporte a streaming do XHR é limitado.
Dependendo da aplicação, podemos conviver com um delay de segundos, por exemplo. Mas algumas aplicações podem ter um overhead na casa dos milisegundos. A melhor forma de transportar dados irá depender.
Polling é muito simples de implementar. Piece of cake. Mas é frequentemente ineficiente. O intervalo de tempo de cada requisição é crítico. Imagine seu navegador fazendo requisições periódicas em frações de segundo para o servidor. Agora imagine milhões de navegadores fazendo a mesma coisa. Um cenário de terror pra qualquer sysadmin. Vamos olhar a função abaixo:
[code language=\\\”javascript\\\”]
function checkUpdates(url){
var xhr = new XMLHttpRequest();
xhr.open(\\\’GET\\\’, url);
xhr.onload = function(){ /* processa atualizações vindas do servidor */ };
xhr.send();
}
setInterval(checkUpdates(\\\’/updates\\\’), 2000);
[/code]
Nesse exemplo, ocorre a checagem por atualizações a cada 2 segundos.
Cada requisição é comumente chamada de ajax. Ele nada mais é que uma requisição HTTP padrão. Muitas dessas requisições serão desnecessárias, pois não virão atualizações na resposta. Dependendo do caso, essas requisições desnecessárias podem ter um custo alto. Podem sobrecarregar a rede e o servidor, além de acabar com a bateria de dispositivos móveis. Uma requisição HTTP 1.x tem aproximadamente 800 bytes sem cookies. Imagine milhares de clientes trafegando 800 bytes a cada 2 segundos. E agora? Websocket? Ainda não. E se existisse uma maneira de eliminar essas requisições desnecessárias? Pior que existe ó.
Long-Polling
Long-polling, a.k.a COMET, a.k.a HTTP push, a.k.a Ajax reverso. Esta técnica nos permite manter a mesma conexão até que a atualização esteja disponível.
A conexão fica aberta até a atualização estar disponível. Uma vez que a resposta é entregue ao cliente, a conexão é fechada e outra requisição long-polling é enviada ao servidor, aguardando a próxima mensagem.
[code language=\\\”javascript\\\”]
function checkUpdates(url){
var xhr = new XMLHttpRequest();
xhr.open(\\\’GET\\\’, url);
xhr.onload = function(){
…
checkUpdates(\\\’/updates\\\’);
};
xhr.send();
}
checkUpdates(\\\’/updates\\\’);
[/code]
Pode testar. A bagaça realmente funciona. Mas e aí? Long-polling é sempre eficiente? Não. Só será eficiente quando o intervalo de tempo de atualizações no servidor for mais ou menos constante. Caso contrário, pode gerar mais requisições ao servidor do que o polling com setInterval.
Em alguns casos, long-polling resolve. A primeira versão do chat do facebook utilizava essa técnica. No entanto, hoje existem formas mais eficientes como websocket e server-sent events. Mais eficientes e bem mais trabalhosos.
Até a próxima.
Deixe um comentário