segunda-feira, 4 de julho de 2011

Simulando multi-thread em JavaScript

Quem desenvolve para Web sabe o poder e a dor de cabeça que é trabalhar com JavaScript. Por um lado, é muito legal desenvolver uma interface bem dinâmica para o usuário sem que a página seja o tempo todo recarregada. Por outro lado, é bastante incômodo e muito comum aparecer aquelas janelinhas chatas de travamento quando tentamos inserir códigos que executam operações mais complexas.

Uma das coisas mais chatas (entre muitas outras, como depurar um código em JavaScript, que pode ser um exercício de paciência e interpretação descomunais) é que em JavaScript, o código é executado em uma única thread. Isso significa que quando a execução fica parada em um ponto, nada mais poderá ser executado. Quando temos um código JavaScript muito pesado executando, é comum o navegador travar e exibir uma janela perguntando se desejamos encerrar o script. Mas às vezes esse processamento é necessário e seria muito bom poder executar a parte mais pesada dessa tarefa em background.

A linguagem não permite que isso seja feito, mas existe uma maneira de simular esse comportamento, utilizando temporizadores (timers) para postergar a execução do código ou de parte do código mais custoso. A forma encontrada está descrita (em inglês) em um texto escrito por James Edwards. O artigo apresenta, em linhas gerais, uma forma para simular múltiplas linhas de execução em JavaScript, utilizando a função setInterval para executar, de tempos em tempos, trechos de um laço que seja muito pesado. Dessa forma, evita-se que o navegador trave e pode-se executar um pedaço da tarefa de cada vez, sem travar toda a execução.

Um sério problema que eu tive com essa abordagem foi com o uso de referências para objetos que dentro da função do setInterval. Simplesmente não foi possível acessá-las. Uma solução, inspirada pelo texto escrito no Zetafleet, pelo Colin (também em Inglês), que desencoraja o uso de setInterval por uma série de razões. Re-implementei, então, a sugestão de James Edwards utilizando o setTimeout e o código funcionou perfeitamente.

Outra iniciativa interessante que encontrei quando tentava solucionar o meu problema foi o Concurrent.Thread, que é um projeto para implementar uma execução virtual de multi threading em JavaScript. O projeto ainda está em desenvolvimento, mas a idéia é muito interessante.

Nenhum comentário:

Postar um comentário