2010-11-06 4 views
0

J'essaie de trouver le meilleur moyen d'exécuter mes fonctions dans le bon ordre.Flux de travail AJAX: Comment commander l'exécution de ces fonctions?

j'ai 3 fonctions

fonction 1 - squirts OPTIONs dans un SELECT via JSON et les marque comme sélectionné
fonction 2 - squirts OPTIONS dans un deuxième SELECT et les marque comme sélectionné
fonction 3 - obtient le Les valeurs des SELECT ci-dessus avec certaines valeurs INPUT supplémentaires, font un AJAX GET résultant en données JSON, qui est lu et remplit une table.

Avec JQuery Onload, j'Execute:

function1(); 
function2(); 
function3(); 

Je trouve function3 est l'exécution avant Selects ont été renseignés avec des options et donc la table n'a aucun résultat, parce que les valeurs envoyées dans l'EEG étaient vides . Je sais que c'est probablement un problème très simple et qu'il y a probablement une douzaine de façons d'y parvenir, mais fondamentalement, j'ai besoin de la meilleure façon de coder ceci pour que function3 ne fonctionne que si function1 et 2 sont terminés.

Je suis arrivé en Javascript via la porte arrière après avoir appris les bases de JQuery en premier!

Merci pour votre aide.

Répondre

0

invoquer function2 à l'intérieur de function1 et function3 à l'intérieur de function2.

+0

Cela fonctionnera pour mon exécution initiale, mais je veux appeler ces fonctions plus tard et je ne veux pas qu'ils exécutent des fonctions secondaires à chaque fois. –

+0

faire 2 variables en dehors de la portée de toutes les 3 fonctions et les mettre à false, les mettre à vrai à l'intérieur de la fonction 1 et la fonction 2 quand ils déclenchent la fonction 2 et la fonction 3 et invoquer seulement cette dernière. –

+0

@Neil burton, utilisez-vous des appels ajax dans ces fonctions. Si vous utilisez des appels ajax, ils sont des appels asynchrones, la fonction démarre l'ajax et passe à la fonction suivante. – kobe

0

Il n'est pas clair pourquoi f1 et f2 s'exécutent avant f3.

Etes-vous également en train d'utiliser le $ (document) .ready() préféré ou une variante d'onload?

Il peut être utile de fournir un scénario de test reproductible.

1

Javascript s'exécute de manière synchrone, ce qui signifie que function3 doit attendre function2 pour terminer, qui doit attendre que function1 se termine avant l'exécution.

L'exception est lorsque vous exécutez du code asynchrone, comme setTimeout, setInterval ou une requête AJAX asynchrone.

Tout code ultérieur qui repose sur l'achèvement d'un tel code asynchrone doit être appelé de telle sorte qu'il ne s'exécute pas tant que le code asynchrone n'est pas terminé. Dans le cas du setTimeout, vous pouvez simplement placer l'appel de fonction suivant à la fin de la fonction que vous transmettez au setTimeout.

Dans le cas d'un appel AJAX, vous pouvez placer l'appel de fonction suivant dans un rappel qui se déclenche lors d'une demande terminée.

Si vous ne voulez pas que l'exécution de la fonction suivante se produise à chaque fois, vous pouvez modifier vos fonctions pour accepter un argument de fonction qui est appelé à la fin du code asynchrone.

Quelque chose comme:

function function1(fn) { 
    setTimeout(function() { 
     // your code 
     // Call the function parameter if it exists 
     if(fn) { 
      fn(); 
     } 
    }, 200); 
} 

function function2() { 
    // some code that must wait for function1 
} 

onload:

// Call function1 and pass function2 as an argument 
function1(function2); 

// ...or call function1 without the argument 
function1(); 

// ...or call function2 independently of function1 
function2(); 
0

fun3() ne fonctionnent après que les deux sont prêts. Il pourrait courir deux fois. Vous pouvez corriger cela avec un verrou à l'intérieur de fun3() vous aurez besoin d'un Singleton pour vous assurer qu'il fonctionne correctement.

var select1ready = false, select2ready = false; 

fun1() 
{ 
    // do stuff 
    select1ready = true; 
    fun3(); 
} 

fun2() 
{ 
    // do stuff 
    select2ready = true; 
    fun3(); 
} 

fun3() 
{ 
    if (select1ready && select2ready) 
    { 
    } 
} 


fun1(); 
fun2(); 
1

Je vous recommande d'utiliser une bibliothèque promesses. Vous pouvez pirater des solutions simples comme d'autres réponses le suggèrent, mais au fur et à mesure que votre application grandit, vous découvrirez que vous faites de plus en plus de ces hacks. Les promesses sont destinées à résoudre ce genre de problèmes en traitant des appels asynchrones.

Le projet CommonJS a several Promises proposals que vous devez extraire. Voici un question I asked on SO about Promises un bon moment avec des liens vers d'autres solutions. En savoir plus sur les promesses dans this Douglas Crockford video. Toute la vidéo est bonne, mais passez à mi-chemin pour des promesses. J'utilise actuellement la bibliothèque FuturesJS pour répondre à mes besoins. Mais il existe également des avantages pour d'autres implémentations. Il vous permet de faire sequences très facilement:

// Initialize Application 
Futures.sequence(function (next) { 
    // First load the UI description document 
    loadUI(next); // next() is called inside loadUI 
}) 
.then(function(next) { 
    // Then load all templates specified in the description 
    loadTemplates(next); // next() is called inside loadTemplates 
}) 
.then(function(next) { 
    // Then initialize all templates specified in the description 
    initTemplates(); 
}); 

Encore plus puissant est quand vous devez join événements async ensemble et faire une autre action lorsque tous les autres événements ont terminé async. Voici un exemple (non testé) qui charge un tas de fichiers HTML, puis effectuer une action qu'une seule fois tous ont terminé le chargement:

var path = "/templates/", 
    templates = ["one.html","two.html","three.html"], 
    promises = []; 

$.each(templates, function(i,name) { 
    promises[i] = Futures.promise(); 
    var $container = $("<div>"); 
    $container.load(path+name, function(response,status,xhr) { 
     promises[i].fullfill(); 
    } 
}); 

Futures.join(promises, {timeout: 10000}) // Fail if promises not completed in 10 seconds 
    .when(function(p_arr) { 
     console.log("All templates loaded"); 
    }) 
    .fail(function(p_arr) { 
     console.log("Error loading templates"); 
    }); 

Cela pourrait être surpuissant pour votre application. Mais si l'application est de plus en plus complexe, l'utilisation de promesses vous aidera à long terme.

J'espère que cela aide!

+1

l'API plus récente fore Futures.Sequence est .then (fonction (suivant, arg1, arg2, ...) {next (newArg1, newArg2, ...)}) – CoolAJ86

+0

@ CoolAJ86 - merci de clarifier, je viens d'éditer la réponse . Notez que 'loadUI' et' loadTemplates' font des appels AJAX asynchrones, donc je leur passe 'next', et ils appellent' next() 'une fois terminé. – Tauren

Questions connexes