dmsLiveList: Lista de itens em Tempo Real com AJAX

No meu local de trabalho temos um Portal de notícias e uma intranet. Na intranet apresentamos noticias do Portal, como ela esta sendo reformulada, decidi me livrar do iframe e buscar alguma forma de manter uma lista de notícias atualizadas sem que isto ocorra junto a um refresh da página.

Como a necessidade é a mãe de toda invenção, surgiu a idéia de usar AJAX de forma a satisfazer esta minha necessidade. Comecei então este script, simples inspirado na seção “DiggSpy” do Digg.com . Veja como podemos implementar este script no resto do post.

Objetivos do Script

Buscar, em intervalos determinados de tempo, novos itens de uma fonte qualquer de dados. De forma que apenas seja atualizada a lista se houver um item novo.

Fluxo de atividade

Fluxo de dados - dmsLiveList

De uma forma simples esta é a ideia do que o script deve realizar para cumprir o objetivo citado acima.

Para explicar melhor o funcionamento do script vou dividi-lo em X partes, que podem refletir os passos que testei antes de consolidar um script completo. São estas:

1. Inicialização/Resgate de dados 2. Obtenção da lista/Retorno de dados (Backend) 3. Atualização/População dos dados

1 – Inicialização/Resgate dos Dados

Com experiências passadas em AJAX a questão do resgate dos dados era bem simples, porém, a inicialização, após analisar o projeto como um todo, trouxe alguns problemas que precisava contornar. Ao iniciar o script deveria buscar um numero determinado de itens, de forma a popular a lista preenchendo todas as “vagas”, na outra mão durante a execução devemos receber apenas um novo item de cada vez.

 this.listLength = 5; //número de elementos a apresentar this.iniLoad = this.listLength; //Número de itens a serem carregados no primeiro load

this.init = function(){ me.showLoading(); me.getNewItems(); if (me.\_firstLoad) me.\_firstLoad = 0; //indica primeiro load me.updateList(); }

Além disso temos outro problema. Como a requisição XMLHttpRequest é executada de forma paralela, corre-se o risco de o script de atualização se adiantar à primeira chamada e ocasionar um erro de javascript, ou uma longa espera (tempo entre atualizações) até o conteúdo aparecer. Com isso foi necessário adicionar ao script um loop que verificasse o estado do request, e repetisse a chamada do update em intervalos consideravelmente menores. Fora estas ações, verifiquei a necessidade de apresentar um div de carregamento, que indicasse que o conteúdo estava sendo obtido.

 //Continuar repetindo a chamada de atualização até o conteudo chegar if (!me.resultReady){ me.\_timer = setTimeout( function(){ me.updateList(); }, 500); return false; } 
 //Carregar código de loading e indicar que esta mostrando loading this.showLoading = function (){ me.\_target.innerHTML = "

![](load.gif/)

"; me.\_loadingState = 1; }

Para fazer a requisição utilizei os comandos crus, criando um request e enviando uma simples requisição GET, e apontando para uma função da parte 3, o tratamento dos dados de retorno.

me.ajaxReq.open("POST", me.ajaxTarget, true); me.ajaxReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); me.ajaxReq.onreadystatechange = me.insertNewItems; if (me.\_firstLoad){ params = "iniLoad="+this.iniLoad; }else{ params = null; } me.ajaxReq.send(params);

2 - Obtenção da lista/Retorno de dados (Backend)

Esta parte do script foi desenvolvida em PHP, e como exemplo deste script criei dois retornos diferentes. Um script busca dados de um RSS da internet, e o outro retorna frases randômicas sempre que é chamado, simulando uma situação de uma lista com alta freqüência de atualização.

Em comum estes dois scripts precisam de um flag que permita retornar o numero necessário de itens na primeira chamada, e retornar os dados finais em um formato padrão, neste caso XML. A forma como produzir estes dados e suas fontes é a variação entre eles.

$limit = ($\_POST\[iniLoad\] > 0)? $\_POST\[iniLoad\]:"1";

Buscando dados de um RSS

Aqui tivemos um desafio, determinar quais itens eram realmente novos no RSS. Para isso tivemos de utilizar variáveis de sessão, já que as outras formas sempre falhavam em um ou outro RSS.

if (!in\_array($insItem->guid,$\_SESSION\[dmsSpy\_read\]) || $\_POST\[iniLoad\]){

Frases Randômicas

Este script é mais um “tampa buraco” para poder mostrar dados mais pertos da realidade. Tudo é feito de forma simples, montando um array de palavras, escolhendo uma seqüência aleatória e retornando ela.

function randomSentence($length){ $ostring = "texto longo, origem das palavras (obtido no gerador de Lero-Lero)"; $available = array\_unique(explode(" ",$ostring)); $nwords = count($available); for($i = 0; $i< $length; $i++){ $chamada .= $available\[rand(0,$nwords)\]." "; } return trim(strtolower($chamada)); }

3- Atualização ou População dos dados

O recebimento dos dados é feito de forma simples, adicionando divs no começo da lista e removendo o ultimo da lista. Para isso foi utilizado um array que armazena os IDs dos DIVS apresentados, combinado com funções de PUSH e SHIFT para adicionar e remover os itens do array.

 var it = me.\_new.shift();

id = "spy\_"+it\['id'\]; newdiv = document.createElement('div'); newdiv.id = id; newdiv.className = 'spy'; newdiv.innerHTML = "

"+it\['value'\]+""; newdiv.style.display = 'none';

me.\_target.insertBefore(newdiv,me.\_olddiv); me.\_olddiv = newdiv;

me.\_shown.push(id);

Para criar o efeito como o do Spy que foi minha inspiração, decidi usar a biblioteca Scriptaculous, que deve estar presente. Porém, como nem todos desejam usar esta biblioteca ou até ter efeitos especiais, implementei uma configuração simples que desabilita os efeitos, deixando o script mais “seco” mas mantendo sua funcionalidade.

this.effects = 1; //Usar ou não Script.aculo.us

Espero que este script seja útil, sintam-se a vontade para alterá-lo e utilizar em suas soluções, mas peço que por favor deixem alguma referencia para este blog.

Veja uma demostração do script Faça o download

comments powered by Disqus

Related Posts

PHP Conference Brasil 09 - T minus 1+1/2 Day

PHP Conference Brasil 09 - T minus 1+1/2 Day

  • November 25, 2009

So one and a half days before the conference i finally got around to setting up for a video blog about the conference, stealing the idea from Cal Evans and Eli White, let’s see how it goes!

Read More
2009: Um ano do PHP no Brasil e no mundo

2009: Um ano do PHP no Brasil e no mundo

  • December 15, 2009

Enquanto sento aqui em frente ao Wordpress e lendo meu post sobre 2008 eu vejo que este ano realmente foi um ano de muita mudança e sucesso.

Read More
Debugging PHPUnit Tests in NetBeans with XDebug

Debugging PHPUnit Tests in NetBeans with XDebug

  • May 13, 2011

Every now and then you run into this weird situation in your code, where something that was supposed to zig is now zagging and it makes no sense whatsoever.

Read More