A reprodução não autorizada é proibida
1. Processamento de cálculos caros
Talvez o aspecto mais complexo do desenvolvimento de aplicativos Javascript complexos seja a natureza de thread único da interface do usuário. A melhor situação quando o Javascript lida com a interação do usuário é a resposta lenta, e a pior situação é a falta de resposta, fazendo com que o navegador trave (quando o Javascript é executado, todas as operações de atualização na página são suspensas). Devido a este facto, é imperativo reduzir todas as operações complexas (qualquer cálculo com duração superior a 100ms) a um nível controlável. Além disso, se o script não parar após ser executado por pelo menos 5 segundos, alguns navegadores (como Firefox e Opera) gerarão uma caixa de aviso para avisar o usuário de que o script não responde.
Obviamente, isso é indesejável e produzir uma interface que não responde não é bom. No entanto, este é quase certamente o caso quando você precisa processar grandes quantidades de dados (como processar milhares de elementos DOM).
Neste momento, o cronômetro é particularmente útil. Como o cronômetro pode efetivamente pausar a execução do código Javascript, ele também pode impedir que o navegador interrompa o código em execução (desde que o código individual não seja suficiente para fazer com que o navegador trave). Com isso em mente, podemos incorporar cálculos de loop normais e intensivos em cálculos sem bloqueio. Vejamos o exemplo a seguir, onde esse tipo de cálculo é necessário.
Uma tarefa de longa duração:
<table><tbody></tbody></table>
// Operação normal, intensiva
var tabela = document.getElementsByTagName("tbody");
for ( var i = 0; i < 2000; i++ ) {
var tr = document.createElement("tr");
for ( var t = 0; t < 6; t++ ){
var td = document.createElement("td");
td.appendChild(document.createTextNode("" + t));
tr.appendChild(td);
}
tabela.appendChild(tr);
}
}
Neste exemplo, criamos um total de 26.000 nós DOM e preenchemos os números em uma tabela. Isso é muito caro e provavelmente travará o navegador e impedirá a interação normal do usuário. Podemos introduzir temporizadores nisso e obter resultados diferentes, talvez melhores.
Use temporizadores para interromper tarefas de longa duração:
<table><tbody></tbody></table>
var tabela = document.getElementsByTagName("tbody");
var i = 0, máx = 1999;
setTimeout(função(){
for ( var passo = i + 500; i < passo; i++ ) {
var tr = document.createElement("tr");
for ( var t = 0; t < 6; t++ ){
var td = document.createElement("td");
td.appendChild(document.createTextNode("" + t));
tr.appendChild(td);
}
}
tabela.appendChild(tr);
}
se (eu <máx)
setTimeout(argumentos.callee, 0);
}, 0);
Em nosso exemplo modificado, dividimos a computação intensiva em quatro partes, cada uma criando 6.500 nós. É improvável que esses cálculos interrompam o fluxo normal do navegador. O pior cenário é que esses números possam ser ajustados a qualquer momento (por exemplo, fazê-los variar entre 250-500, para que cada uma de nossas células gere 3.500 nós DOM). Mas o mais impressionante é como mudamos nosso código para nos adaptarmos ao novo sistema assíncrono. Precisamos trabalhar mais para garantir que os números dos elementos sejam gerados corretamente (o loop não termina para sempre). O código é muito semelhante ao nosso original. Observe que usamos encerramentos para manter o estado de iteração entre fragmentos de código. Sem encerramentos, este código será sem dúvida mais complexo.
Há uma clara mudança no uso desta tecnologia em relação ao original. Longos travamentos do navegador são substituídos por 4 atualizações visuais da página. Embora o navegador tente executar esses trechos de código o mais rápido possível, ele também renderiza alterações no DOM (como atualizações massivas) após cada etapa do cronômetro. Na maioria dos casos, os usuários desconhecem esse tipo de atualização, mas é importante lembrar que elas acontecem.
Há uma situação em que essa tecnologia funcionaria especificamente para mim: um aplicativo que construí para calcular horários de estudantes universitários. No início a aplicação era típica de CGI (o cliente conversava com o servidor, o servidor calculava o agendamento e devolvia). Mas mudei e coloquei todos os cálculos de cronograma no cliente. Essa é a visualização dos cálculos de cronograma:
Esses cálculos são bastante caros (milhares de permutações precisam ser percorridas para encontrar a resposta correta). Este problema é resolvido dividindo o cálculo do cronograma em unidades reais (atualizando a interface do usuário com a peça concluída). No final, os usuários entregaram uma interface de usuário rápida, responsiva e utilizável.
Muitas vezes é surpreendente o quão útil a tecnologia pode ser. Você o verá frequentemente usado em programas de longa duração, como caixas de teste (discutiremos isso no final deste capítulo). Mais importante ainda, esta tecnologia nos mostra como é fácil contornar as limitações do ambiente do navegador e, ao mesmo tempo, fornecer aos usuários uma experiência rica.