164 votes

Comment dois-je appeler 3 fonctions pour les exécuter les unes après les autres?

Si j'ai besoin d'appeler ces fonctions l'un après l'autre,

        $('#art1').animate({'width':'1000px'},1000);        
        $('#art2').animate({'width':'1000px'},1000);        
        $('#art3').animate({'width':'1000px'},1000);        

Je sais en jQuery que je pouvais faire quelque chose comme:

        $('#art1').animate({'width':'1000px'},1000,'linear',function(){
            $('#art2').animate({'width':'1000px'},1000,'linear',function(){
                $('#art3').animate({'width':'1000px'},1000);        
            });        
        });        

Mais, supposons que je ne suis pas à l'aide de jQuery et je veux l'appeler:

        some_3secs_function(some_value);        
        some_5secs_function(some_value);        
        some_8secs_function(some_value);        

Comment je doit appeler cette fonction pour exécuter some_3secs_function, et APRÈS que la fin de l'appel, puis exécutez some_5secs_function et APRÈS que la fin de l'appel, puis appel some_8secs_function?

Mise à JOUR:

Cela ne fonctionne toujours pas:

    (function(callback){
        $('#art1').animate({'width':'1000px'},1000);
        callback();
    })((function(callback2){
        $('#art2').animate({'width':'1000px'},1000);
        callback2();
    })(function(){
        $('#art3').animate({'width':'1000px'},1000);
    }));

Trois animations démarrent en même temps

Où est mon erreur.

261voto

Peter Olson Points 30452

En Javascript, il y a synchrones et asynchrones fonctions.

Synchrone Fonctions

La plupart des fonctions en Javascript sont synchrones. Si vous deviez faire appel à plusieurs fonctions synchrones dans une rangée

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

elles s'exécutent dans l'ordre. doSomethingElse ne démarre pas jusqu'à ce qu' doSomething a terminé. doSomethingUsefulThisTime, à son tour, ne démarre pas jusqu'à ce qu' doSomethingElse a terminé.

Asynchrone Fonctions

Fonctions asynchrones, cependant, n'allons pas attendre les uns des autres. Penchons-nous sur le même exemple de code que nous avions ci-dessus, cette fois, en supposant que les fonctions sont asynchrones

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

Les fonctions seront initialisés dans l'ordre, mais ils seront tous d'exécuter à peu près à la même époque. Vous ne pouvez pas toujours de prévoir ce qui arrivera en premier: celui qui arrive à prendre le plus court laps de temps pour exécuter va finir premier.

Mais parfois, vous voulez fonctions qui sont asynchrones à exécuter dans l'ordre, et parfois, vous voulez les fonctions qui sont synchrones à exécuter de manière asynchrone. Heureusement, c'est possible avec les rappels et les délais d'attente, respectivement.

Rappels

Supposons que nous avons trois asynchrone fonctions que nous voulons exécuter dans l'ordre, some_3secs_function, some_5secs_function, et some_8secs_function.

Étant donné que les fonctions peuvent être passés comme arguments en Javascript, vous pouvez passer une fonction comme une fonction de callback à exécuter une fois que la fonction est terminée.

Si nous créons les fonctions comme ceci

function some_3secs_function(value, callback){
  //do stuff
  callback();
}

ensuite, vous pouvez appeler puis dans l'ordre, comme ceci:

some_3secs_function(some_value, function() {
  some_5secs_function(other_value, function() {
    some_8secs_function(third_value, function() {
      //All three functions have completed, in order.
    });
  });
});

Délais d'attente

En Javascript, vous pouvez dire une fonction à exécuter après un certain délai (en millisecondes). Cela peut, en effet, faire synchrone fonctions se comportent de manière asynchrone.

Si nous avons trois synchrone fonctions, on peut les exécuter de manière asynchrone à l'aide de l' setTimeout fonction.

setTimeout(doSomething, 10);
setTimeout(doSomethingElse, 10);
setTimeout(doSomethingUsefulThisTime, 10);

C'est, cependant, un peu moche et viole le principe DRY[wikipedia]. Nous avons pu nettoyer un peu les par la création d'une fonction qui accepte un tableau de fonctions et un délai d'attente.

function executeAsynchronously(functions, timeout) {
  for(var i = 0; i < functions.length; i++) {
    setTimeout(functions[i], timeout);
  }
}

Cela peut être appelé de la sorte:

executeAsynchronously(
    [doSomething, doSomethingElse, doSomethingUsefulThisTime], 10);

En résumé, si vous avez asynchrone fonctions que vous souhaitez exécuter syncronously, utilisez des rappels, et si vous avez synchrone fonctions que vous souhaitez exécuter de manière asynchrone, utilisation de délais d'attente.

21voto

lwburk Points 29313

Il semble que vous n'êtes pas pleinement apprécier la différence entre synchrone et asynchrone exécution de la fonction.

Le code que vous avez fourni dans votre mise à jour immédiatement exécute chacune de vos fonctions de rappel, qui à son tour immédiatement démarrer une animation. Les animations, cependant, exécuter asyncronously. Il fonctionne comme ceci:

  1. Effectuer une étape dans l'animation
  2. Appelez setTimeout avec une fonction contenant la prochaine étape de l'animation et d'un retard
  3. Certains le temps passe
  4. La fonction de rappel donnée à l' setTimeout s'exécute
  5. Revenez à l'étape 1

Cela continue jusqu'à la dernière étape de l'animation est terminée. Dans l'intervalle, votre synchrone fonctions ont depuis longtemps terminée. En d'autres termes, votre appel à l' animate fonction ne fait pas vraiment prendre 3 secondes. L'effet est simulé avec des retards et des rappels.

Ce que vous avez besoin est une file d'attente. En interne, jQuery files d'attente les animations, seulement de l'exécution de votre rappel une fois sa correspondante animation est terminée. Si votre rappel commence alors une autre animation, l'effet est qu'ils sont exécutés dans l'ordre.

Dans le cas le plus simple c'est équivalente à la suivante:

window.setTimeout(function() {
    alert("!");
    // set another timeout once the first completes
    window.setTimeout(function() {
        alert("!!");
    }, 1000);
}, 3000); // longer, but first

Voici un général asynchrone en boucle de la fonction. Il va appeler les fonctions dans l'ordre, en attente pour le nombre spécifié de secondes entre chaque.

function loop() {
    var args = arguments;
    if (args.length <= 0)
        return;
    (function chain(i) {
        if (i >= args.length || typeof args[i] !== 'function')
            return;
        window.setTimeout(function() {
            args[i]();
            chain(i + 1);
        }, 2000);
    })(0);
}    

Utilisation:

loop(
  function() { alert("sam"); }, 
  function() { alert("sue"); });

Vous pourriez évidemment le modifier pour prendre configurable temps d'attente ou pour exécuter immédiatement la première fonction ou à l'arrêt de l'exécution lorsqu'une fonction dans la chaîne de retours false ou apply les fonctions dans un contexte spécifié ou à tout autre chose que vous pourriez avoir besoin.

9voto

user406905 Points 1004

vos fonctions doivent prendre une fonction de rappel, qui est appelée à la fin.

 function fone(callback){
...do something...
callback.apply(this,[]);

}

function ftwo(callback){
...do something...
callback.apply(this,[]);
}
 

alors l'utilisation serait comme:

 fone(function(){
  ftwo(function(){
   ..ftwo done...
  })
});
 

4voto

Trass Vasston Points 349
asec=1000; 

setTimeout('some_3secs_function("somevalue")',asec*3);
setTimeout('some_5secs_function("somevalue")',asec*5);
setTimeout('some_8secs_function("somevalue")',asec*8);

Je n'entrerai pas dans une discussion approfondie de setTimeout ici, mais:

  • dans ce cas, j'ai ajouté le code à exécuter en tant que chaîne. c'est le moyen le plus simple pour passer un var dans votre setTimeout-ed fonction, mais les puristes pourront se plaindre.
  • vous pouvez également passer un nom de fonction sans les guillemets, mais aucune variable ne peut être passé.
  • votre code ne pas attendre pour setTimeout pour déclencher.
  • Celui-ci peut être difficile à obtenir autour de votre tête au premier abord: parce que du point précédent, si vous passez une variable à partir de votre appel de la fonction, cette variable n'existe plus au moment où le délai d'attente déclencheurs de l'appel de la fonction sera exécutée et il est de vars disparu.
  • J'ai été connus pour utiliser des fonctions anonymes pour obtenir autour de tout cela, mais il pourrait y avoir une meilleure façon,

4voto

JKM Points 509

Puisque vous l'avez taguée avec javascript, j'utiliserais un contrôle de minuterie puisque les noms de vos fonctions sont 3, 5 et 8 secondes. Alors lancez votre chronomètre, 3 secondes, appelez le premier, 5 secondes en appelez le second, 8 secondes en appelez le troisième, puis lorsque c'est terminé, arrêtez le chronomètre.

Normalement, en Javascript, ce que vous avez est correct car les fonctions s’exécutent les unes après les autres, mais comme il semble que vous essayez de réaliser une animation chronométrée, une minuterie serait votre meilleur choix.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X