Como faço para configurar um temporizador para evitar a sobreposição de chamadas ajax?

Eu tenho uma página em que os resultados da pesquisa são exibidos em uma grade e em um mapa (usando o KML gerado na hora, sobreposto em um mapa do Google incorporado). Eu liguei isso para funcionar como o usuário digita; aqui está o esqueleto do meu código, que funciona:

$(function() {
   //Wire up search textbox
    $('input.Search').bind("keyup", update);
});

update = function(e) {
   //Get text from search box
   //Pass to web method and bind to concessions grid
    $.ajax({  
        ...
        success: function(msg) {
            displayResults(msg, filterParams);
        },
    });

}

displayResults = function(msg, filterParams) {
       //Databind results grid using jTemplates
       //Show results on map: Pass parameters to KML generator and overlay on map
}

Dependendo da pesquisa, pode haver centenas de resultados; e assim o trabalho que acontece em displayResults é intensivo no processador tanto no servidor (consultando o banco de dados, construindo e simplificando o KML em tempo real) quanto no cliente (conectando a grade de resultados, sobrepondo KML grande arquivos no mapa).

Eu gosto do imediatismo de obter resultados progressivamente mais estreitos à medida que digito, mas gostaria de minimizar o número de vezes que isso é atualizado. Qual é a maneira mais simples de introduzir um atraso de N segundos após o usuário parar de digitar, antes de executar a função update ?

1

3 Respostas

Em vez de chamar update() diretamente, chame um wrapper que verifique se há atualizações atrasadas pendentes:

$('input.Search').bind("keyup", delayedUpdate);

function delayedUpdate() {
    if (updatePending) {
        clearTimeout(updatePending);
    }

    updatePending = setTimeout(update, 250);
}

function update() {
    updatePending = false;

    //$.ajax(...
}

Você provavelmente também deve adicionar:

$('input.Search').bind("blur", update);

Isso fará uma atualização imediata quando o usuário sair do campo. Mas certifique-se de também adicionar manipulação para o caso em que o usuário deixa o campo enquanto há uma atualização atrasada pendente (cancele a atualização atrasada primeiro).

3
adicionado
Isso funciona perfeitamente - obrigado.
adicionado o autor Herb Caudill, fonte

Como primeira abordagem, algo como:

$('input.Search').bind("keyup", function() { setTimeout(update, 5) } );

(não tenho certeza sobre a sintaxe exata setTimeout).

Você também pode manter uma variável para controlar se o tempo limite já foi agendado ou não.

0
adicionado
Isso irá efetivamente incorrer na mesma quantidade de carga desnecessária, depois de esperar por 5 milissegundos.
adicionado o autor Ates Goral, fonte

Você pode usar Window.SetTimeOut (YourRefreshMethod), quando o método YourRefereshMethod for chamado, ele irá verificar o número de caracteres sendo digitados até o momento, e compará-lo ao contador, o contador começará com o valor 0, então a chamada inicial não fará nada diferente de atualizar o contador com a contagem de caracteres atuais, a segunda vez que seu método for chamado, ele irá verificar o número de caracteres digitados, se ele corresponde ao número anterior registrado pelo contador, então significa que o usuário não digitou nada novo e você pode disparar o seu método de atualização, caso contrário, você irá atualizar o valor do contador

0
adicionado
JavaScript Brasil OFICIAL
JavaScript Brasil OFICIAL
4 138 dos participantes

Grupo sobre JavaScript do Brasil