web-dev-qa-db-fra.com

Retard synchrone dans l'exécution du code

J'ai un code qui doit être exécuté après un certain délai, disons 5 000 ms.Actuellement, j'utilise setTimeout, mais il est asynchrone et je veux que l'exécution attende son retour. J'ai essayé d'utiliser les éléments suivants:

function pauseComp(ms) 
 {
     var curr = new Date().getTime();
     ms += curr;
     while (curr   < ms) {
         curr = new Date().getTime();
     }
 } 

Mais le code que je veux retarder dessine des objets en utilisant raphaeljs et l'affichage n'est pas du tout lisse. J'essaie d'utiliser le plugin doTimeout. Je n'ai besoin d'un délai qu'une seule fois, car le délai et le code à retarder sont tous deux en boucle. Je n'ai pas d'exigence pour un identifiant donc je ne l'utilise pas ..__ Par exemple:

for(i; i<5; i++){ $.doTimeout(5000,function(){
         alert('hi');  return false;}, true);}

Cela attend 5 secondes avant de donner le premier salut, puis les itérations de boucle successives sont en alerte immédiatement après le premier. Ce que je veux, c’est attendre 5 secondes, donner une alerte, attendre, puis donner une alerte, etc. 

Toutes les astuces/suggestions sont appréciées!

22
kavita

Variation sur la réponse acceptée qui est aussi bonne que celle-ci.

De plus, je suis d’accord avec les mises en garde de préférer les appels de fonction setTimeout et asynchrone, mais parfois, par exemple, lors de la construction de tests, vous avez simplement besoin d’une commande d’attente synchrone ...

function wait(ms) {
    var start = Date.now(),
        now = start;
    while (now - start < ms) {
      now = Date.now();
    }
}

si vous le souhaitez en quelques secondes, divisez le nombre de ms de départ par 1000 en vérifiant tout le temps.

41
ThinkBonobo

JavaScript est un langage à un seul thread. Vous ne pouvez pas combiner les traitements setTimeout et synchrone. Ce qui se passera, c’est que le minuteur s’arrêtera, mais le moteur JS attendra pour traiter les résultats jusqu’à ce que le script en cours s’achève.

Si vous voulez des méthodes synchrones, appelez simplement la méthode!

Si vous souhaitez traiter quelque chose après setTimeout, incluez-le ou appelez-le à partir de la fonction de délai d'attente.

5
OverZealous

J'ai créé une fonction de temporisation synchrone simple. Cela fonctionne de deux manières différentes, rappel et non rappel.

une fonction:

function wait(ms, cb) {
  var waitDateOne = new Date();
  while ((new Date()) - waitDateOne <= ms) {
    //Nothing
  }
  if (cb) {
    eval(cb);
  }
}

exemple de rappel:

wait(5000,"doSomething();");

exemple de non-rappel:

console.log("Instant!");
wait(5000);
console.log("5 second delay");
2
andrew65952

Les boucles sans délai d'attente (qui vérifient l'heure ou comptent jusqu'à 1000000 ou quoi que ce soit) bloquent simplement le navigateur. setTimeout (ou le plugin $.doTimeout) est le meilleur moyen de le faire.

La création de délais d'attente dans une boucle ne fonctionnera pas car la boucle n'attendra pas le délai d'attente précédent avant de continuer, comme vous l'avez découvert. Essayez quelque chose de plus semblable à ceci:

// Generic function to execute a callback a given number
// of times with a given delay between each execution
function timeoutLoop(fn, reps, delay) {
  if (reps > 0)
    setTimeout(function() {
                 fn();
                 timeoutLoop(fn, reps-1, delay);
               }, delay);
}

// pass your function as callback
timeoutLoop(function() { alert("Hi"); },
            5,
            5000);

(Je viens de bricoler cela rapidement, donc bien que je sois confiant que cela fonctionne, il pourrait être amélioré de différentes manières. Par exemple, dans la "boucle", il pourrait passer une valeur d'index à la fonction de rappel afin que votre propre code sache quelle itération c'est en cours, mais j'espère que ça vous aidera à démarrer.)

2
nnnnnn

Si vous souhaitez tirer parti de la nouvelle syntaxe async/wait, vous pouvez convertir le délai imparti en une promesse, puis l'attendre.

function wait(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("Done waiting");
      resolve(ms)
    }, ms )
  })
}  

(async function Main() {
  console.log("Starting...")
  await wait(5000);
  console.log("Ended!")
})();
2
michael_olofinjana

Voici comment utiliser le plugin JQuery doTimeout

jQuery('selector').doTimeout( [ id, ] delay, callback [, arg ... ] );

À partir de docs : "si le rappel renvoie vrai, ledoTimeoutla boucle s'exécutera à nouveau, après le délai, créant une boucle de scrutation jusqu'à ce que le rappel renvoie une valeur non vraie.

var start = Date.now();
console.log("start: ", Date.now() - start);
var i = 0;
$.doTimeout('myLoop', 5000, function() {
  console.log(i+1, Date.now() - start);
  ++i;
  return i == 5 ? false : true;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-dotimeout/1.0/jquery.ba-dotimeout.min.js"></script>

0
user2314737