2017-10-12 3 views
2

jquery, pas de changements avant css longtemps la fonction exec

function doact() { 
 
    $('p.main').addClass("hide"); 
 
    $('p.loading').removeClass("hide"); 
 

 
    //this is only example of long time exec function 
 
    for (var i = 0; i < 1000000000; i++) { 
 
    for (var j = 0; j < 2; j++) {} 
 
    } 
 
    // 
 

 
    $('p.loading').addClass("hide"); 
 
    $('p.main').removeClass("hide"); 
 

 
    alert('done'); 
 
}
.hide { 
 
    display: none; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<p class="loading hide">loading...</p> 
 
<p class="main">bla bla bla</p> 
 
<input id="btn" type="button" value="do action" onclick="doact()" />

Lorsque je clique sur le bouton, loading... ne semble pas et main ne disparaît pas, seul le message fait. Comment peut-on implémenter un tel algorithme?

Répondre

3

Le problème est dû au fait que JS est monothread. Par conséquent, le moteur de rendu n'a pas assez de temps pour repeindre l'interface utilisateur avant de lancer l'énorme boucle. Il ne peut alors mettre à jour qu'après la boucle se termine, à ce moment il cache l'élément, puis le montre de nouveau tout de suite, donc rien ne semble se produire.

Pour résoudre ce problème, exécutez le code de blocage dans un setTimeout() avec un léger délai qui donne à l'interface utilisateur de mettre à jour avant de démarrer la boucle.

Notez également que on* les attributs d'événement doivent être évités. J'ai modifié votre code pour utiliser un gestionnaire discret JS, que vous avez inclus jQuery de toute façon:

$('#btn').click(function() { 
 
    $('p.main, p.loading').toggleClass("hide"); 
 

 
    setTimeout(function() { 
 
    for (var i = 0; i < 1000000000; i++) { 
 
     for (var j = 0; j < 2; j++) {} 
 
    } 
 

 
    $('p.main, p.loading').toggleClass("hide"); 
 
    console.log('done'); 
 
    }, 50); 
 
})
.hide { 
 
    display: none; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> 
 
<p class="loading hide">loading...</p> 
 
<p class="main">bla bla bla</p> 
 
<input id="btn" type="button" value="do action" />

Cela dit, opérations synchrones de longue durée qui bloquent l'interface utilisateur sont très mauvais modèle. Je suggère fortement de refactoriser votre code afin que vous évitiez cela.