web-dev-qa-db-fra.com

utilisation de setTimeout de manière synchrone en JavaScript

J'ai le scénario suivant:

setTimeout("alert('this alert is timedout and should be the first');", 5000);
alert("this should be the second one");

J'ai besoin que le code après le setTimeout soit exécuté après l'exécution du code dans setTimeout. Puisque le code qui vient après le setTimeout n'est pas le mien, je ne peux pas le mettre dans la fonction appelée dans le setTimeout ...

Y a-t-il un moyen de contourner cela?

49
Nathan

Le code est-il contenu dans une fonction?

function test() {
    setTimeout(...);     

    // code that you cannot modify?
}

Dans ce cas, vous pouvez empêcher l'exécution de la fonction, puis la réexécuter:

function test(flag) {

    if(!flag) {

        setTimeout(function() {

           alert();
           test(true);

        }, 5000);

        return;

    }

    // code that you cannot modify

}
60
David Hedlund

Je suis venu dans une situation où j'avais besoin d'une fonctionnalité similaire la semaine dernière et cela m'a fait penser à ce post. Fondamentalement, je pense que l '"attente occupée" à laquelle @AndreKR fait référence, serait une solution appropriée dans de nombreuses situations. Voici le code que j'ai utilisé pour monopoliser le navigateur et forcer une condition d'attente.

function pause(milliseconds) {
        var dt = new Date();
        while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}

document.write("first statement");
alert("first statement");

pause(3000);

document.write("<br />3 seconds");
alert("paused for 3 seconds");

Gardez à l'esprit que ce code maintient réellement votre navigateur. J'espère que cela aide n'importe qui.

37
Nathan

Mettez-le simplement dans le rappel:

setTimeout(function() {
    alert('this alert is timedout and should be the first');
    alert('this should be the second one');
}, 5000);
6
Darin Dimitrov

Non, car il n'y a pas de fonction de retard en Javascript, il n'y a aucun moyen de le faire autre que l'attente occupée (qui verrouillerait le navigateur).

5
AndreKR

ES6 (attente occupée)

const delay = (ms) => {
  const startPoint = new Date().getTime()
  while (new Date().getTime() - startPoint <= ms) {/* wait */}
}

usage:

delay(1000)
4
Andrey

En utilisant ES6 & promesses & async, vous pouvez exécuter les choses de manière synchrone.

Alors, que fait le code?

 1. Calls setTimeOut 1st inside of demo then put it into the webApi Stack
 2. Creates a promise from the sleep function using the setTimeout, then resolves after the timeout has been completed;
 3. By then, the first setTimeout will reach its timer and execute from webApi stack. 
 4. Then following, the remaining alert will show up.


function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  setTimeout("alert('this alert is timedout and should be the first');", 5000);
  await sleep(5000);
  alert('this should be the second one');
}
demo();
2
РАВИ
setTimeout(function() {
  yourCode();    // alert('this alert is timedout and should be the first');
  otherCode();   // alert("this should be the second one");
}, 5000);
2
Marcel Jackwerth

Vous pouvez essayer de remplacer window.setTimeout par votre propre fonction, comme ceci

window.setTimeout = function(func, timeout) {
    func();
}

Qui peut ou peut ne pas fonctionner correctement du tout. En plus de cela, votre seule option serait de changer le code d'origine (ce que vous avez dit que vous ne pouviez pas faire)

Gardez à l'esprit que la modification de fonctions natives comme celle-ci n'est pas exactement une approche très optimale.

0
Jani Hartikainen