Je souhaite effectuer trois appels ajax dans un événement de clic. Chaque appel ajax effectue une opération distincte et renvoie les données nécessaires pour un rappel final. Les appels eux-mêmes ne dépendent pas les uns des autres, ils peuvent tous se dérouler en même temps, mais j'aimerais avoir un dernier rappel lorsque les trois sont terminés.
$('#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*/});
});
Réponses:
Voici un objet de rappel que j'ai écrit dans lequel vous pouvez soit définir un seul rappel pour qu'il se déclenche une fois que tout est terminé, soit laisser chacun avoir son propre rappel et les déclencher une fois tous terminés:
REMARQUER
Depuis jQuery 1.5+, vous pouvez utiliser la méthode différée comme décrit dans une autre réponse:
Exemple de différé ici
pour jQuery <1.5, ce qui suit fonctionnera ou si vous avez besoin de déclencher vos appels ajax à des moments inconnus, comme indiqué ici avec deux boutons: déclenché après avoir cliqué sur les deux boutons
[usage]
pour un seul rappel une fois terminé: exemple de travail
chacun ayant son propre rappel lorsque tout est terminé: Exemple de travail
[Le code]
la source
setCallback
pour en ajouter plus à la file d'attente. Bien que maintenant que j'y pense ... je devrais l'appeleraddCallback
ou quelque chose du genre ... et pas seulement définir car il s'ajoute à la file d'attentesingleCallback
variable de la deuxième ligne est-elle inutile? Ou est-ce que je manque quelque chose?On dirait que vous avez des réponses à cela, mais je pense qu'il y a quelque chose qui mérite d'être mentionné ici qui simplifiera grandement votre code. jQuery a introduit le
$.when
dans la v1.5. On dirait:Je ne l'ai pas vu mentionné ici, j'espère que cela aide.
la source
Ne voyant pas le besoin d'un objet malarky moi-même. Simple a une variable qui est un entier. Lorsque vous démarrez une demande, augmentez le nombre. Quand on termine, décrémente-le. Lorsqu'il est nul, il n'y a aucune demande en cours, donc vous avez terminé.
la source
if (!--inProgress)
. La version correcte est analogue àinProgress = inProgress - 1; if (inProgress == 0) { /* do stuff */ }
. La forme compacte combine l' opérateur de décrémentation de préfixe (--
) et l'opérateur de négation (!
) pour évaluer à «vrai» (et donc exécuter leif
bloc), si la décrémentationinProgress
aboutitinProgress == 0
, et s'évalue à «faux» (et donc ne fait rien) autrement.Il est intéressant de noter que puisque
$.when
s'attend à toutes les requêtes ajax en tant qu'arguments séquentiels (pas un tableau), vous verrez couramment$.when
utilisé.apply()
comme ceci:C'est parce que
$.when
accepte des arguments comme celui-ciEt pas comme ça:
la source
all
méthode ou quelque chose de similaire, mais j'aime le concept de carte. Agréable.J'aime l'idée de hvgotcodes. Ma suggestion est d'ajouter un incrémenteur générique qui compare le nombre complet au nombre nécessaire, puis exécute le rappel final. Cela pourrait être intégré dans le rappel final.
[Modifié pour refléter les mises à jour de nom.]
la source
EDIT - la meilleure option serait peut-être de créer un point de terminaison de service qui fait tout ce que font les trois demandes. De cette façon, vous n'avez qu'à faire une seule demande, et toutes les données sont là où vous en avez besoin dans la réponse. Si vous constatez que vous faites les mêmes 3 demandes encore et encore, vous voudrez probablement emprunter cette voie. Il est souvent judicieux de mettre en place un service de façade sur le serveur qui regroupe les actions de serveur plus petites couramment utilisées. Juste une idée.
une façon de le faire serait de créer un objet 'sync' dans votre gestionnaire de clics avant les appels ajax. Quelque chose comme
La synchronisation sera automatiquement liée à la portée des appels réussis (fermeture). Dans le gestionnaire de réussite, vous incrémentez le nombre et s'il est égal à 3, vous pouvez appeler l'autre fonction.
Sinon, vous pouvez faire quelque chose comme
lorsque chaque succès est exécuté, la valeur de la synchronisation devient true. Vous devrez vérifier la synchronisation pour vous assurer que les trois sont vrais avant de continuer.
Notez le cas où l'un de vos xhrs ne renvoie pas de succès - vous devez en tenir compte.
Encore une autre option serait d'appeler toujours la fonction finale dans vos gestionnaires de succès et de lui faire accéder à l'option de synchronisation pour déterminer s'il faut réellement faire quelque chose. Vous devrez cependant vous assurer que la synchronisation est dans le cadre de cette fonction.
la source
J'ai posé la même question il y a quelque temps et j'ai obtenu quelques bonnes réponses ici: Meilleur moyen d'ajouter un `` rappel '' après une série d'appels XHR asynchrones
la source
J'ai eu de bons indices à partir des réponses sur cette page. Je l'ai un peu adapté à mon usage et j'ai pensé pouvoir partager.
Il y a quelques limitations ici, mais pour mon cas c'était correct. J'ai également trouvé que pour des choses plus avancées, il existe également un plugin AOP (pour jQuery) qui pourrait être utile: http://code.google.com/p/jquery-aop/
la source
Je suis tombé sur ce problème aujourd'hui, et c'était ma tentative naïve avant de regarder la réponse acceptée.
la source
Ce n'est pas jquery (et il semble que jquery a une solution viable) mais juste comme une autre option ...
J'ai eu des problèmes similaires avec les services Web SharePoint: vous devez souvent extraire des données de plusieurs sources pour générer des entrées pour un seul processus.
Pour le résoudre, j'ai intégré ce type de fonctionnalité dans ma bibliothèque d'abstraction AJAX. Vous pouvez facilement définir une requête qui déclenchera un ensemble de gestionnaires une fois terminée. Cependant, chaque requête peut être définie avec plusieurs appels http. Voici le composant (et la documentation détaillée):
DPAJAX sur DepressedPress.com
Cet exemple simple crée une demande avec trois appels, puis transmet ces informations, dans l'ordre des appels, à un seul gestionnaire:
Notez que contrairement à la plupart des autres solutions (y compris, je crois, la solution "quand" dans jquery) à condition que cette méthode ne force pas le threading unique des appels en cours - chacune fonctionnera toujours aussi rapidement (ou aussi lentement) que l'environnement le permet mais le gestionnaire unique ne sera appelé que lorsque tout sera terminé. Il prend également en charge la définition des valeurs de délai d'expiration et les tentatives de relance si votre service est un peu floconneux.
Je l'ai trouvé incroyablement utile (et incroyablement simple à comprendre du point de vue du code). Plus de chaînage, plus de comptage des appels et d'économie de sortie. Il suffit de régler et oublier".
la source
Ok, c'est vieux mais laissez-moi vous apporter ma solution :)
Cela fonctionne également avec les fonctions qui ont un rappel. Vous définissez le syncCount et vous appelez la fonction sync (...) dans le rappel de chaque action.
la source
J'ai trouvé un moyen plus simple de le faire sans avoir besoin de méthodes supplémentaires pour organiser une file d'attente.
JS
PHP (ajax1.php)
PHP (ajax2.php)
la source
Par défaut, toutes les demandes sont envoyées de manière asynchrone (c'est-à-dire que ce paramètre est défini sur true par défaut). Si vous avez besoin de requêtes synchrones, définissez cette option sur
false
. Les requêtes etdataType: "jsonp"
requêtes entre domaines ne prennent pas en charge le fonctionnement synchrone. Notez que les demandes synchrones peuvent temporairement verrouiller le navigateur, désactivant toutes les actions pendant que la demande est active. Depuis jQuery 1.8 , l'utilisation deasync: false
avec jqXHR ($.Deferred
) est obsolète; vous devez utiliser les options de rappel success / error / complete au lieu des méthodes correspondantes de l' objet jqXHR telles quejqXHR.done()
or the deprecatedjqXHR.success()
.la source
Je suis désolé mais je ne peux pas expliquer ce que je veux parce que je suis un coréen qui ne peut même pas parler un mot en anglais. mais je pense que vous pouvez facilement le comprendre.
la source