Estou republicando esse artigo pois o mesmo recebeu um comentário, e ao mesmo tempo, é um assunto que ainda assola muitas pessoas que utilizam jQuery, principalmente quem começou com ela há pouco tempo.
Qual webdeveloper nunca usou jQuery? Muito difícil… Bom, mas vamos falar de algo que nem todos os developers
que usam jQuery se atentam ao programar. Eu mesmo fui pego hoje por um gap que me tomou alguns minutos da tarde…
Algumas funções (na verdade, a maioria nesse framework) recebem outras funções como callback, aquela função que será chamada assim que a instrução/função chamada acabar seu procedimento. Um exemplo muito utilizado em aplicações reais são as
Funções Ajax
load( url, data, callback )
Returns: jQuery. Load HTML from a remote file and inject it into the DOM.
jQuery.get( url, data, callback, type )
Returns: XMLHttpRequest. Load a remote page using an HTTP GET request.
jQuery.getJSON( url, data, callback )
Returns: XMLHttpRequest. Load JSON data using an HTTP GET request.
Ao usar a função load, você carrega um arquivo remoto (seja ele html puro ou um arquivo dinâmico, como PHP ou outra linguagem), mas o tempo que ele leva para ser processado nem sempre é igual. E se você precisa esperar que o conteúdo seja totalmente carregado antes de proceder com o script?Colocar um timeout? No way, uma vez que você não tem controle sobre o tempo de execução em todas as plataformas e clientes… Logo, o Callback está aí para sanar essa questão.
Porém…
Temos que tomar cuidado ao usar o Callback, uma vez que o desempenho dos sistemas ainda podem afetar a funcionalidade de seu código, e fazer você perder várias horas de seu precioso descanso…Veja esse trecho de código que trabalhei recentemente:
jQuery().ready(function() {
jQuery.getJSON('/php/data.drafts.php?l=10&f=json', function(data){
jQuery.each(data, function(i, item){
jQuery('#latestDraftsTable tbody').append('<tr><td>'+item.id+'</td><td>' + item.title + '</td><td>' + item.date+ '</td></tr>');
});
});
jQuery('#latestDraftsTable').tablesorter({widgets: ['zebra']});
);
Alguém consegue perceber o erro, ou melhor, a Zebra? Muito difícil. Mas ao rodar o código, não acontecia o esperado: que minha tabela apresentasse o comportamento de uma tabela ordenável que o jQuery UI tablesorter plugin proporciona (ou seja, deu Zebra e não ocorreu a Zebra). Aí eu descobri o problema: a penúltima linha do código nem estava sendo executada… Seriam Gaps de performance?
Diferentes paradigmas
Fosse uma linguagem das antigas qualquer, onde o paradigma procedural imperava, esse código não teria problema, pois cada instrução só seria disparada ao final da anterior. No Javascript, a coisa não é bem assim, ainda mais quando se trata de AJAX -Assynchronous Jacascript and XML – uma requisição que é disparada e outra estrutura interna fica encarregada de processar os resultados quando eles chegarem. Ao efetuar a função getJSON, a requisição é disparada, e já passamos para a próxima linha (onde eu chamo o tablesorter na tabela), porém, não deu tempo da requisição JSON retornar e popular a tabela. Resultado: minha tabela fica populada mas não fica ordenável.
Graças a um amigo developer fera em JS, eu consegui perceber isso e reordenaro código de maneira que ele funcionasse como o esperado:
Código corrigido
jQuery().ready(function() {
jQuery.getJSON('/php/data.drafts.php?l=10&f=json', function(data){
jQuery.each(data, function(i, item){
jQuery('#latestDraftsTable tbody').append('<tr><td>'+item.id+'</td><td>' + item.title + '</td><td>' + item.date+ '</td></tr>');
});
jQuery('#latestDraftsTable').tablesorter({widgets: ['zebra']});
});
);
Assim, o tablesorter vai ocorrer dentro do callback, logo após ter terminado de ser populada a tabela. Na realidade, os callbacks foram feitos exatamente para situações como essa: quando a coisa vai demorar um pouco e você não tem certeza do quanto…
OI Thomas, eu me deparei com esse problema e desconfiei deste comportamento, e agora tenho a certeza lendo seu artigo. Muito bom, parabéns.
Você tem alguma sugestão de workaround quando o retorno do callback precisa ser esperado, por exemplo, em combos aninhadas.
Tenho três combos aninhadas, e quando escolho a primeira ela preenche a segunda, mas o evento da segunda já está disparando antes mesmo da combo finalizar a opçoes…
Obrigado
Cara, é possível a função load carregar uma página web sem ser arquivo remoto? Se não, existe alguma outra função que execute isso?
Se você quer se referir a um arquivo no próprio servidor, é possível sim: basta você passar o caminho relativo dela ou até mesmo o absoluto (/arquivo.ext). Agora, se você quiser redirecionar o usuário para outra página, você pode usar
window.location.href = '/arquivo.ext';Se ainda não for isso, me explica o que gostaria de fazer que vejo se posso ajudar.