J'exécute une boucle et dans la boucle j'appelle une fonction. La fonction effectue un appel ajax et renvoie une réponse mais le problème est que la boucle n'attend pas la réponse, donc la fonction retourne undefined.
function checkBidStatus(index) {
$.ajax({
type:'get',
url:'/orderbook/checkorderdetails',
success: function(data){
$parsedData = JSON.parse(data);
if($parsedData[index]) {
return "Hello";
} else {
return "Bye";
}
//$("#bid-details .modal-dialog").html(data);
},
error: function (response) {
console.log(response);
}
});
}
let content = '';
for(let i = 1; i <= 10; i++ ) {
content += '<div>' +
(checkBidStatus(i)) +
'</div>';
}
3 Réponses :
Pourquoi ne pas utiliser une promesse à l'intérieur et attendre cette promesse pour obtenir le résultat requis, après quoi vous mettez à jour le DOM? Dans votre méthode checkBidStatus, vous pouvez créer une promesse et la renvoyer. Lorsque le résultat ajax est disponible, résolvez la promesse avec le résultat ajax.
L'appelant de la méthode devra attendre la résolution de la promesse, puis mettre à jour le DOM.
let content = '';
for(let i = 1; i <= 10; i++ ) {
checkBidStatus(i).then(result => {
content += '<div>' +result + '</div>';
})
}
Remarque: je n'ai pas testé le code, mais quelque chose de similaire devrait marcher. De plus, l'ordre des divs créés à partir de l'index n'est pas garanti, vous devrez peut-être vous en occuper, si l'ordre est important.
Je trouve ça plutôt sympa. Je pense qu'une combinaison de nos réponses devrait le faire avancer :)
Vous devriez attendre la réponse du serveur pour chaque itération en boucle.
let content = '';
let i = 1;
while (i <= 10) {
let { msg, index } = checkBidStatus(i);
content += '<div>' + msg + '</div>';
i = index;
}
}
function checkBidStatus(index) {
$.ajax({
type: 'get',
url: '/orderbook/checkorderdetails',
success: function(data) {
$parsedData = JSON.parse(data);
if ($parsedData[index]) {
return {
msg: 'Hello',
index: index + 1,
};
} else {
return {
msg: 'Bye',
index: index + 1,
};
}
//$("#bid-details .modal-dialog").html(data);
},
error: function(response) {
console.log(response);
},
});
Le problème est que la boucle for est synchrone, mais l'appel ajax est asynchrone. Par exemple, cette fonction doit attendre que le serveur réponde. Par conséquent, les rappels ou les promesses doivent être utilisés par l'appelant avant de passer à la requête suivante.
Il existe des moyens élégants d'accomplir cette tâche en utilisant certaines bibliothèques, telles que async, mais la méthode "quick vanillaJS" pour résoudre cette tâche en utilisant les promesses seraient quelque chose comme ceci:
function multipleRequests(){
checkBidStatus(requestCnt)
.then((resp) => { // This runs if the promise RESOLVES (i.e., success)
content = contentTemplate.replace('[BID_RESULT]', resp.msg);
// --- [then do what you want with content] --- //
// Request again
requestCnt++;
if( requestCnt < nRequests ){
multipleRequests();
}
})
.catch(console.error) // This runs if promise rejects (i.e., has an error)
}
// Run:
multipleRequests();
Ensuite, vous pouvez continuer à appeler cette fonction de manière récursive:
const contentTemplate = '<div>[BID_RESULT]</div>';
const nRequests = 10;
var requestCnt = 0;
var content = '';
function checkBidStatus(index) {
return new Promise((resolve, reject) => {
$.ajax({
type:'get',
url:'/orderbook/checkorderdetails',
success: function(data){
$parsedData = JSON.parse(data);
resolve({ index: index + 1, msg: $parsedData ? "Hello" : "Bye" });
},
error: reject
});
// <-- NOTE: there is no return statement at this line. Hence if
// you were to call this function from your for loop, you'd see
// undefined
}
}
Le problème est que la boucle for est synchrone, mais l'appel ajax est asynchrone. Par exemple, cette fonction doit attendre que le serveur réponde. Par conséquent, les rappels ou les promesses doivent être utilisés par l'appelant avant de passer à la demande suivante.
plz élaborer avec du code
Ok ... en cours. Code à venir.
Vous pouvez rendre l'appel ajax synchrone, en définissant le
async: falsedans le corps ajax. c'est la solution facile mais cela bloque également votre thread d'interface utilisateur, ce qui signifie que votre interface utilisateur ne répondra pas pendant la boucle.@ ayan_84 synchrone Ajax est obsolète en raison de la mauvaise expérience utilisateur qu'il offre. Il verrouille le navigateur pendant l'utilisation et une longue requête (ou une série de requêtes) peut donner à l'utilisateur l'impression que la page s'est plantée. De plus, comme il est obsolète, vous pouvez vous attendre à ce que les navigateurs cessent de le prendre en charge dans un avenir prévisible. Ce n'est pas une bonne façon de résoudre le problème. Le chaînage des promesses serait une solution plus appropriée
@Adyson, ce n'est clairement pas recommandé, mais actuellement, cela résoudra son objectif
@AJ, De plus, votre code a besoin d'une correction, le retour d'un rappel de succès ne fonctionne pas en fait comme un retour de checkBidStatus (). Essayez d'utiliser une variable locale pour checkBidStatus (), puis attribuez cette variable dans le rappel de réussite
Copie possible de Javascript - requête AJAX dans les boucles
Je viens de fournir une implémentation possible en utilisant des promesses (voir aussi: Promise < / a>). Il existe des solutions beaucoup plus élégantes / idéales qui tirent parti des bibliothèques, mais le code que je fournis est destiné à expliquer le problème.