segunda-feira, dezembro 17, 2007

Chamadas Periódicas Sem Atropelo

Recentemente, precisei criar uma página que fazia chamadas periódicas ao servidor, para saber se um determinado processamento longo havia acabado, e carregar os resultados no caso positivo. No Rails, a melhor maneira de se fazer isso é com a função periodically_call_remote, que dispara uma chamada AJAX em intervalos regulares. Mas, aí, como é de praxe, encontrei um pequeno problema quando o código foi para o ambiente de integração. As chamadas são assíncronas (o primeiro A do AJAX), acontecendo a cada X segundos, mas a chamada que finalmente carregava os resultados demora mais de X segundos para ser completa. Então, no meio do carregamento, uma outra chamada era iniciada e terminava justo a tempo de substituir a maravilhosa tela de resultados pela tela de "por favor espere".

Tornar as chamadas síncronas resolvia este problema, mas fazia o browser congelar completamente nos n*X segundos que a resposta demorava para carregar. Então, a saída que eu acabei utilizando foi criar uma variável de "estado", manipulada pelos callbacks do Prototype, para garantir que apenas uma chamada assíncrona executasse por vez.

Este é o resultado:



<script>
var stop_polling = false;
var polling = false;
</script>
<%= periodically_call_remote(
:url => ping_search_search_results_url(@search),
:method => :get,
:frequency => 3,
:condition => "stop_polling == false && polling == false",
:after => "polling = true",
:complete => "polling = false"
) %>


A primeira variável ("stop_polling") tem seu valor mudado pelo servidor quando os resultados ficam prontos. A segunda é alterara pelo próprio script para impedir que uma nova chamada seja executada enquanto a anterior ainda está esperando sua resposta. Com isso, o browser do usuário não congela.

Nenhum comentário: