Quero fazer três chamadas ajax em um evento de clique. Cada chamada ajax faz uma operação distinta e retorna os dados necessários para um retorno de chamada final. As chamadas em si não são dependentes uma da outra, todas elas podem ir ao mesmo tempo; no entanto, eu gostaria de ter um retorno de chamada final quando todas as três estiverem concluídas.
$('#button').click(function() {
fun1();
fun2();
fun3();
//now do something else when the requests have done their 'success' callbacks.
});
var fun1= (function() {
$.ajax({/*code*/});
});
var fun2 = (function() {
$.ajax({/*code*/});
});
var fun3 = (function() {
$.ajax({/*code*/});
});
Respostas:
Aqui está um objeto de retorno de chamada que escrevi, no qual você pode definir um único retorno de chamada para disparar uma vez concluído, ou permitir que cada um tenha seu próprio retorno de chamada e acioná-los todos quando terminar:
AVISO PRÉVIO
Desde o jQuery 1.5+, você pode usar o método adiado, conforme descrito em outra resposta:
Exemplo de diferido aqui
para jQuery <1.5, o seguinte funcionará ou se você precisar que suas chamadas ajax sejam acionadas em horários desconhecidos, como mostrado aqui com dois botões: acionado após o clique de ambos os botões
[uso]
para retorno de chamada único depois de concluído: Exemplo de Trabalho
cada um com seu próprio retorno de chamada quando tudo estiver concluído: Exemplo de Trabalho
[O código]
fonte
setCallback
para adicionar mais à fila. Embora, agora que penso nisso ... Eu deveria chamá-loaddCallback
ou algo do tipo ... e não apenas definir uma vez que está adicionando para a filasingleCallback
variável na 2ª linha é desnecessária? Ou eu estou esquecendo de alguma coisa?Parece que você tem algumas respostas para isso, no entanto, acho que há algo que vale a pena mencionar aqui que simplificará bastante o seu código. O jQuery introduziu o
$.when
na v1.5. Parece que:Não o vi mencionado aqui, espero que ajude.
fonte
Não vendo a necessidade de nenhum objeto mal-intencionado. Simples tem uma variável que é um número inteiro. Quando você inicia uma solicitação, aumente o número. Quando alguém terminar, diminua-o. Quando é zero, não há solicitações em andamento, então você está pronto.
fonte
if (!--inProgress)
. A versão correta é análoga ainProgress = inProgress - 1; if (inProgress == 0) { /* do stuff */ }
. A forma compacta combina o operador de decremento--
do prefixo ( ) e o operador de negação (!
) para avaliar como "true" (e, portanto, executar oif
bloco), se a decrementarinProgress
resultar eminProgress == 0
, e avalia como "false" (e, portanto, não faz nada) caso contrário.É importante notar que desde que
$.when
espera que todos os pedidos de ajax como argumentos seqüenciais (não um array) você vai comumente ver$.when
usado com.apply()
assim:Isso ocorre porque
$.when
aceita argumentos como esteE não é assim:
fonte
all
método ou algo semelhante, mas eu gosto do conceito de mapa. Agradável.Eu gosto da ideia dos hvgotcodes. Minha sugestão é adicionar um incrementador genérico que compare o número completo com o número necessário e execute o retorno de chamada final. Isso pode ser incorporado no retorno de chamada final.
[Editado para refletir as atualizações de nome.]
fonte
EDIT - talvez a melhor opção seja criar um terminal em serviço que faça tudo o que as três solicitações fazem. Dessa forma, você só precisa fazer uma solicitação e todos os dados estão onde você precisa que eles estejam na resposta. Se você achar que está fazendo os mesmos três pedidos repetidamente, provavelmente desejará seguir esse caminho. Geralmente, é uma boa decisão de design configurar um serviço de fachada no servidor que agrupa geralmente ações menores do servidor. Apenas uma ideia.
Uma maneira de fazer isso seria criar um objeto 'sync' no seu manipulador de cliques antes que o ajax chame. Algo como
A sincronização será vinculada ao escopo das chamadas de sucesso automaticamente (fechamento). No manipulador de sucesso, você incrementa a contagem e, se for 3, pode chamar a outra função.
Como alternativa, você poderia fazer algo como
quando cada sucesso é executado, ele altera o valor na sincronização para true. Você precisaria verificar a sincronização para garantir que todos os três sejam verdadeiros antes de continuar.
Observe o caso em que um dos seus xhrs não retorna com êxito - você precisa dar conta disso.
Outra opção seria sempre chamar a função final em seus manipuladores de sucesso e acessar a opção de sincronização para determinar se realmente deve fazer alguma coisa. Você precisaria garantir que a sincronização esteja no escopo dessa função.
fonte
Fiz a mesma pergunta há um tempo e recebi algumas boas respostas aqui: Melhor maneira de adicionar um 'retorno de chamada' após uma série de chamadas XHR assíncronas
fonte
Recebi boas dicas das respostas desta página. Eu o adaptei um pouco para o meu uso e pensei em compartilhar.
Existem algumas limitações aqui, mas para o meu caso, tudo bem. Também descobri que, para coisas mais avançadas, também existe um plug-in AOP (para jQuery) que pode ser útil: http://code.google.com/p/jquery-aop/
fonte
Hoje me deparei com esse problema e essa foi minha tentativa ingênua antes de assistir à resposta aceita.
fonte
Não é jquery (e parece que o jquery tem uma solução viável), mas apenas como outra opção ....
Eu tive problemas semelhantes ao trabalhar muito com os serviços Web do SharePoint - muitas vezes você precisa extrair dados de várias fontes para gerar entrada para um único processo.
Para resolvê-lo, integrei esse tipo de funcionalidade na minha biblioteca de abstração AJAX. Você pode definir facilmente uma solicitação que acionará um conjunto de manipuladores ao concluir. No entanto, cada solicitação pode ser definida com várias chamadas http. Aqui está o componente (e documentação detalhada):
DPAJAX em DepressedPress.com
Este exemplo simples cria uma solicitação com três chamadas e passa essas informações, na ordem de chamada, para um único manipulador:
Observe que, diferentemente de muitas outras soluções (inclusive, acredito que a solução "quando" no jquery), desde que esse método não force o encadeamento único das chamadas feitas - cada uma ainda será executada tão rapidamente (ou tão lentamente) quanto o ambiente permitir mas o manipulador único será chamado somente quando todos estiverem concluídos. Ele também suporta a configuração de valores de tempo limite e novas tentativas se o seu serviço for um pouco ruim.
Eu achei incrivelmente útil (e incrivelmente simples de entender da perspectiva do código). Chega de encadeamento, contagem de chamadas e economia de saída. Basta configurá-lo e esquecê-lo".
fonte
Ok, isso é antigo, mas deixe-me contribuir com minha solução :)
Também funciona com funções que possuem retorno de chamada. Você define o syncCount e chama a função sync (...) no retorno de chamada de cada ação.
fonte
Encontrei uma maneira mais fácil de fazer isso sem a necessidade de métodos extras que organizam uma fila.
JS
PHP (ajax1.php)
PHP (ajax2.php)
fonte
Por padrão, todas as solicitações são enviadas de forma assíncrona (ou seja, isso é definido como verdadeiro por padrão). Se você precisar de solicitações síncronas, configure esta opção para
false
. Solicitações entre domínios edataType: "jsonp"
solicitações não suportam operação síncrona. Observe que solicitações síncronas podem bloquear temporariamente o navegador, desativando qualquer ação enquanto a solicitação estiver ativa. A partir do jQuery 1.8 , o uso deasync: false
com jqXHR ($.Deferred
) está obsoleto; você deve usar as opções de retorno de chamada com êxito / erro / concluir , em vez dos métodos correspondentes do objeto jqXHR , comojqXHR.done()
o obsoletojqXHR.success()
.fonte
Me desculpe, mas não posso explicar o que escrevo porque sou coreano que não consegue nem falar uma palavra em inglês. mas acho que você pode entender facilmente.
fonte