quinta-feira, 12 de julho de 2007

Funcionalidade de Thread/Timer em JavaScript

Bom, digamos que o título não está exatamente bom, mas não consegui pensar em nenhum melhor =/

Ontem estava precisando fazer um lance parecido com o "Thread.sleep(numero);", ou melhor, acho que era mais parecido com o "Timer.schedule()", porém em JavaScript, e lembrei do tal conhecido método setTimeout(). Ele funciona, de uma maneira simplificada, assim:


<>
<>
var contador=0;
function testeTimeout()
{
document.getElementById('contador').innerHTML = contador++;
setTimeout('testeTimeout()',1000);
}
< /script>

< onload="testeTimeout()">
< id="contador">
< /div>
< /body>
< /html>


O que ele faz é "agendar" a execução do método passado no primeiro parametro, depois do tempo setado (que é em milisegundos) no segundo parametro. Ou seja, no exemplo acima ele iré executar o metodo testeTimeout(), e irá "agendar" uma próxima execução deste método para daqui a 1 segundo.

Um exemplo prático do uso disso seria fazer um agendamento de processamento de método (function) javaScript, para por exemplo, ficar fazendo um pooling via ajax em um determinado Serviço publicado pelo Application Server.

Outro aspecto interessante ainda sobre essa função é:
"Ela é blocante ou não?"
A resposta para esta pergunta é NÃO. Existem 2 situações onde ela poderia bloquear:
ter mais instruções no método logo abaixo da chamada de setTimeout
chamar outro método através de um evento qualquer por intervensão do usuário por exemplo.

Segue abaixo um exemplo para comprovar os dois exemplos. O timeout agora foi setado para 10 segundos para que seja possível a interação do usuário (clicar no botão):

<>
<>
var contador=0;
var contador2 =0;
function testeTimeout()
{
document.getElementById('contador').innerHTML = contador++;
setTimeout('testeTimeout()',10000);
for(i=0; i<10; i++)
{
contador2++;
document.getElementById('contador2').innerHTML =
document.getElementById('contador2').innerHTML+' '+contador2;
}
}

function alerta()
{
document.getElementById('contador2').innerHTML = 'outra função';
alert('teste');
}
< /script>

< onload="testeTimeout()">
< id="contador">
< /div>
< id="contador2">
< /div>
< type="button" value="Alerta" onclick="alerta()">
< /body>
< /html>


Concluindo, você pode, por exemplo, deixar um "serviço em background" na sua aplicação e ele não irá interferir no funcionamento geral, dentre outras inúmeras funcionalidades.

------
Pode até não ser tão grande novidade, mas agora quando precisar algo já tenho os exemplos prontos aqui (o que é uma coisa que normalmente perco) =)

4 comentários:

girino disse...

Postei no meu blog há algum tempo uns exemplos mais práticos de como usar isso "na vida real" e de como misturar isso com orientação por objetos em javascript. Se quiser dar uma olhada: www.girino.org

Rafael Borba disse...

Na verdade o resto do codigo interfere no funcionamento de setInterval e setTimeout.

Sempre que um comando demorar mais que o tempo de timeout dessas funcoes ela nao executara por enquanto.

Isso acontece porque javaScript nao utiliza Threads verdadeiros.

EX:

Se voce chama uma funcao de um componente XPCOM para copiar um arquivo, e esta copia demorar digamos, 2 minutos, os "intervals" nao funcionarao nesse meio tempo.

Anônimo disse...
Este comentário foi removido por um administrador do blog.
Anônimo disse...
Este comentário foi removido por um administrador do blog.