Comment faire tous les appels AJAX séquentielle?
j'utilise jQuery. Et je ne veux pas d'appels AJAX parallèles sur mon application, chaque appel doit attendre le précédent avant de commencer. Comment la mettre en œuvre? Il n'y a aucune aide?
UPDATE S'il existe une version synchrone de la XMLHttpRequest ou jQuery.post, je voudrais savoir. Mais séquentielle != synchrone, et je voudrais une solution asynchrone et séquentielle.
11 réponses
Il y a une bien meilleure façon de faire cela que d'utiliser des appels ajax synchrones. Jquery ajax retourne un différé de sorte que vous pouvez juste utiliser canalisation enchaînement pour s'assurer que chaque appel ajax termine avant les prochaines courses. Voici un exemple de travail avec un plus en profondeur exemple, vous pouvez jouer avec sur jsfiddle.
// How to force async functions to execute sequentially
// by using deferred pipe chaining.
// The master deferred.
var dfd = $.Deferred(), // Master deferred
dfdNext = dfd; // Next deferred in the chain
x = 0, // Loop index
values = [],
// Simulates $.ajax, but with predictable behaviour.
// You only need to understand that higher 'value' param
// will finish earlier.
simulateAjax = function (value) {
var dfdAjax = $.Deferred();
setTimeout(
function () {
dfdAjax.resolve(value);
},
1000 - (value * 100)
);
return dfdAjax.promise();
},
// This would be a user function that makes an ajax request.
// In normal code you'd be using $.ajax instead of simulateAjax.
requestAjax = function (value) {
return simulateAjax(value);
};
// Start the pipe chain. You should be able to do
// this anywhere in the program, even
// at the end,and it should still give the same results.
dfd.resolve();
// Deferred pipe chaining.
// What you want to note here is that an new
// ajax call will not start until the previous
// ajax call is completely finished.
for (x = 1; x <= 4; x++) {
values.push(x);
dfdNext = dfdNext.pipe(function () {
var value = values.shift();
return requestAjax(value).
done(function(response) {
// Process the response here.
});
});
}
certaines personnes ont commenté qu'elles n'avaient aucune idée de ce que fait le code. Pour le comprendre, vous devez d'abord comprendre les promesses javascript. Je suis assez sûr promises sera bientôt une fonctionnalité de langage javascript natif, ce qui devrait vous donner une bonne motivation pour apprendre.
Vous avez deux choix que je peux penser. L'une consiste à les enchaîner par des rappels. L'autre consiste à rendre les appels synchrones plutôt qu'asynchrones.
y a-t-il une raison pour laquelle vous les voulez séquentiels? Qui va ralentir les choses.
pour rendre l'appel synchrone, vous définirez l'option async dans L'appel Ajax À false. Voir la documentation à http://docs.jquery.com/Ajax/jQuery.ajax#options (cliquez sur l'onglet options pour les voir).
mettre le async option à false, par exemple,
$.ajax({ async: false /*, your_other_ajax_options_here */ });
Référence: Ajax / jQuery.ajax
Vous pourriez donner récit javascript essayer http://www.neilmix.com/narrativejs/doc/
je n'ai jamais utilisé moi-même. Si je voulais le faire, je mettrais en place une sorte d'abstraction pour enchaîner les actions asynchrones. Comme d'autres l'ont dit, la version synchone de l'objet ajax bloque le traitement des événements en attendant une réponse. Cela provoque le navigateur ressemble, il est gelé jusqu'à ce qu'il reçoit une réponse.
la meilleure façon de le faire est d'enchaîner les rappels Comme Nosredna l'a dit. Je ne recommande pas l'utilisation de XMLHttpRequest synchrone car ils verrouillent toute votre application.
il n'y a pas beaucoup d'aide pour ce que je sais, mais vous pourriez faire quelque chose qui ressemble à un FIFO de rappel.
Regardez cette: http://docs.jquery.com/Ajax/jQuery.ajax (cliquez sur l'onglet "options").
mais rappelez-vous qu'un appel synchrone va geler la page jusqu'à ce que la réponse soit reçue, de sorte qu'elle ne peut pas être utilisée dans un site de production, parce que les utilisateurs vont se fâcher si, pour une raison quelconque, ils doivent attendre 30 secondes avec leur navigateur gelé.
EDIT: ok, avec votre mise à jour c'est plus clair ce que vous voulez atteindre ;)
ainsi, votre code peut sembler comme ceci:
$.getJSON("http://example.com/jsoncall", function(data) {
process(data);
$.getJSON("http://example.com/jsoncall2", function (data) {
processAgain(data);
$.getJSON("http://example.com/anotherjsoncall", function(data) {
processAgainAndAgain(data);
});
});
});
ainsi, le deuxième appel ne sera émis que lorsque la réponse au premier appel aura été reçue et traitée, et le troisième appel ne sera émis que lorsque la réponse au deuxième appel aura été reçue et traitée. Ce code est pour getJSON mais il peut être adapté à $.Ajax.
Et semble maintenant vous avez une solution pour cela:
http://api.jquery.com/category/deferred-object/
ou
http://www.slideshare.net/furf/making-ajax-sexy-jsconf-2010?from=ss_embed
les appels synchrones ne sont pas nécessairement plus lents, si vous avez une application où les appels AJAX s'ouvrent, postent, puis ferment une socket, les appels multiples à la socket n'ont pas de sens car certaines sockets ne peuvent gérer qu'une seule connexion, dans ce cas, la mise en file d'attente des données de sorte qu'elle ne soit envoyée que lorsque L'appel AJAX précédent est terminé signifie un débit de données beaucoup plus élevé.
(async () => {
for(f of ['1.json','2.json','3.json']){
var json = await $.getJSON(f);
console.log(json)
};
})()
- demandes 3 fichiers json avec jQuery, les appels ajax
- processus dans l'ordre (pas en parallèle) avec attendent
- fonctionne dans Chrome/Firefox/Edge (comme de 1/30/2018)
plus MDN
Que Diriez-vous d'utiliser le noeud.js événements?
var EventEmitter = require('events').EventEmitter;
var eventEmitter = new EventEmitter();
var $ = require('jquery');
var doSomething = function (responseData) {
var nextRequestData = {};
// do something with responseData
return nextRequestData;
};
// ajax requests
var request1 = $.ajax;
var request2 = $.ajax;
var requests = [request1, request2];
eventEmitter.on('next', function (i, requestData) {
requests[i](requestData).then(
function (responseData) {
console.log(i, 'request completed');
if (i+1 < requests.length) {
var nextRequestData = doSomething(responseData);
eventEmitter.emit('next', i+1, nextRequestData);
}
else {
console.log('completed all requests');
}
},
function () {
console.log(i, 'request failed');
}
);
});
var data = {
//data to send with request 1
};
eventEmitter.emit('next', 0, data);
séquentielle != synchrone, et je voudrais une solution asynchrone et séquentielle
l'exécution synchrone signifie généralement "utiliser la même horloge", tandis que l'exécution séquentielle signifie "suivre dans l'ordre ou la séquence".
pour votre cas d'utilisation spécifique, je pense que les deux conditions doivent être remplies, car l'exécution asynchrone implique la possibilité d'un résultat non séquentiel.