2009-09-21 5 views
16

Salut à tous. J'ai, ce qui semble être, un problème trivial. J'ai le code JavaScript suivant:jQuery: Attendez que la fonction soit terminée pour continuer le traitement?

$(function() { 
    var r = GetResults(); 

    for(var i = 0; i < r.length; i++) { 
     // Do stuff with r 
    } 
}); 

function GetResults() { 
    $.getJSON("/controller/method/", null, function(data) { 
     return data; 
    }); 
} 

En raison du fait que j'appelle une méthode de manière asynchrone, le script continue à exécuter et quand il rencontre la boucle, r est évidemment pas avoir encore une valeur. Ma question est la suivante: quand j'ai une méthode qui fait une opération asynchrone, et je suis dépendant des données qu'elle retourne dans le bloc principal, comment puis-je arrêter l'exécution jusqu'à ce que les données soient retournées? Quelque chose comme:

var r = GetResults(param, function() { 

}); 

où la fonction est une fonction de rappel. Je ne peux pas déplacer le traitement pour la boucle dans la fonction de rappel de la demande JSON parce que je réutilise la fonctionnalité de GetResults plusieurs fois dans la page, sauf si je veux dupliquer le code. Des idées?

Répondre

13

déplacez votre bloc "faire des choses avec r" dans votre callback $ .getJSON. vous ne pouvez pas faire des choses avec r jusqu'à ce qu'il ait été livré, et la première occasion que vous aurez à utiliser r est dans le rappel ... alors faites-le alors.

$(function() { 
    var r = GetResults(); 
}); 

function GetResults() { 
    $.getJSON("/controller/method/", null, function(data) { 
     for(var i = 0; i < data.length; i++) { 
      // Do stuff with data 
     } 
     return data; 
    }); 
} 
+0

Merci pour la réponse. La raison pour laquelle j'ai séparé GetResults est que je réutilise cette fonctionnalité plusieurs fois sur la page. Je devrais éditer mon post pour le dire. – user135383

+0

Si vous devez effectuer le même traitement sur des données provenant de plusieurs endroits, il suffit de remplacer votre fonction de rappel par une fonction nommée et d'y effectuer le traitement. $ .getJSON ("/ controller/méthode /", null, processData (données)); function processData (d) {...} –

3

Vous pouvez le faire:

$(function() { 
    PerformCall();   
}); 

function PerformCall() { 
    $.getJSON("/controller/method/", null, function(data) { 
     for(var i = 0; i < data.length; i++) { 
     // Do stuff with data 
     } 
    }); 
} 
0

Ce n'est pas possible. Soit vous rendez votre fonction synchrone, soit vous modifiez la conception de votre code pour supporter l'opération asynchrone.

0

Déplacer le traitement des données dans le rappel:

$(function() { 
    GetResults(); 
}); 

function GetResults() { 
    $.getJSON("/controller/method/", null, function(data) { 

     for(var i = 0; i < data.length; i++) { 
      // Do stuff with data 
     } 
    }); 
} 
+0

cela ne marchera pas. votre déclaration de retour reviendra du rappel, pas de GetResults. Cette solution ne fonctionnera jamais car elle n'utilise pas correctement les rappels. – mkoryak

+0

@mkoryak Merci. J'ai supprimé le retour du rappel. – ctford

7

Ajax vous donne déjà un rappel, vous êtes censé l'utiliser:

function dostuff(data) { 
    for(var i = 0; i < data.length; i++) { 
     // Do stuff with data 
    } 
}; 
$(document).ready(function() { 
    $.getJSON("/controller/method/", null, dostuff); 
}); 
2

La réponse courte est que vous ne pouvez pas bloquer sur une opération asynchrone ... ce qui est bien sûr le sens de "asynchrone". Au lieu de cela, vous devez modifier votre code pour utiliser un rappel pour déclencher l'action en fonction des données renvoyées par l'appel $.getJSON(...). Quelque chose comme ce qui suit devrait fonctionner:

$(function() { 
    GetResults(); 
}); 

function GetResults() { 
    $.getJSON("/controller/method/", null, function(data) { 
    for(var i = 0; i < data.length; i++) { 
     // Do stuff with data 
    } 
    }); 
} 
2

Compte tenu de vos exigences mises à jour ...

Je ne peux pas déplacer le pour le traitement de la boucle dans la fonction de rappel de la demande JSON parce que je suis réutilisant les fonctionnalité de GetResults plusieurs temps dans toute la page, sauf si je voulez dupliquer le code. Des idées?

... vous pouvez modifier GetResults() d'accepter une fonction en tant que paramètre, que vous auriez alors exécuter comme $.getJSON rappel (avertissement de code air):

$(function() { 
    GetResults(function(data) { 
     for(var i = 0; i < data.length; i++) { 
      // Do stuff with data 
     } 
    }); 
}); 

function GetResults(callback) { 
    $.getJSON("/controller/method/", null, callback); 
} 

Comme vous pouvez le voir général Il est préférable de ne pas essayer de combattre le modèle de programmation jQuery asynchrone.:)

0

Vous pouvez avoir un rappel avec des paramètres qui devraient fonctionner bien ...

$(function() { 
    GetResults(function(data) { 
     for(var i = 0; i < data.length; i++) { 
     // Do stuff with data 
     } 
    }); 

}); 

function GetResults(func) { 
    $.getJSON("/controller/method/", null, func); 
} 
7

J'ai rencontré quelque chose de semblable auparavant. Vous devrez exécuter l'appel ajax de manière synchrone.

Voici mon exemple de travail:

$.ajax({ 
    type: "POST", 
    url: "/services/GetResources", 
    contentType: "application/json; charset=utf-8", 
    dataType: "json", 
    data: '{resourceFileName:"mapedit",culture:"' + $("#lang-name").val() + '"}', 
    cache: true, 
    async: false, // to set local variable 
    success: function(data) { 
     localizations = data.d; 
    } 
}); 
+0

Cela fonctionne certainement, mais il bloque le fil de l'interface utilisateur, n'est-ce pas? (Peut-être est-ce acceptable, bien que cela ne semble pas nécessaire compte tenu des informations que nous avons à ce jour.) –

+0

Oui, il bloque, mais bien sûr seulement pour la durée de la demande. Je ne vois pas d'autre moyen, compte tenu de ce que vous cherchez. Je suis allé sur la même route et suis allé sur la route de synchronisation. – ScottE

Questions connexes