5

Lors d'une méthode qui dure 10 secondes pour ajouter des éléments au code HTML, le fichier gif animé ne bouge pas du tout, donnant l'impression que la page Web est bloquée. De toute façon autour de ça.Image animée ne bougeant pas pendant l'appel de méthode javascript long

code Exemple:

 
    $('#button).click(function() { 
     showAnimatedGif(); 
     longRunningMethod();  
     hideAnimatedGif(); 
    }); 

Une façon de contourner cela est de rupture la longue méthode de fonctionnement en plusieurs étapes et l'animation de cette façon, mais vous devez écrire votre code de cette façon pour chaque méthode à long fonctionnement. Vous voulez savoir s'il y a un autre moyen de le faire?

+0

[Ne faites pas cela alors] (http://www.jargon.net/jargonfile/d/Dontdothatthen.html). Vous savez que JavaScript n'est pas multithread, n'est-ce pas? –

+0

Je le sais, mais il doit y avoir des moyens de le faire. – mrjohn

+0

Que fait 'showAnimatedGif()'? Que fait 'longRunningMethod()'? Pouvez-vous poster plus de code? – karim79

Répondre

6

La seule façon de s'assurer que l'animation se produit réellement est que longRunningMethod cède périodiquement au navigateur. Il n'est pas rare que le thread de rendu de l'interface utilisateur bloque sur le thread JavaScript. Par conséquent, les modifications apportées au DOM ne sont pas affichées avant la prochaine exécution du thread JavaScript. Vous pouvez céder en appelant setTimeout avec un délai d'expiration de 0 (qui sera plus long que 0ms   — évidemment   — sur la plupart des implémentations de navigateurs, beaucoup pince cette valeur à au moins 4ms et peut-être jusqu'à 10ms).

Exemple: Voici un script qui ajoute 500 divs, mais donne le navigateur aucune occasion de montrer les travaux en cours ou (généralement) animer quoi que ce soit:

jQuery(function($) { 

    $("#btnGo").click(function() { 
    var n; 

    display("Loading..."); 

    for (n = 0; n < 500; ++n) { 
     $("<div/>").html("Div #" + n).appendTo(document.body); 
    } 

    display("Done loading"); 

    function display(msg) { 
     $("<p/>").html(msg).appendTo(document.body); 
    } 
    }); 

});​ 

Live example * Example with spinner graphic

Comme vous pouvez voyez, il ne cède jamais, et donc quand vous cliquez sur le bouton, la page se bloque pendant un moment, puis tous les 500 divs et les messages apparaissent.

contraste avec cette autre extrémité du spectre, ce qui donne entre chaque div:

jQuery(function($) { 

    $("#btnGo").click(function() { 
    display("Loading..."); 

    addDivs(0, 500, function() { 
     display("Done loading"); 
    }); 

    function addDivs(current, max, callback) { 
     if (current < max) { 
     $("<div/>").html("Div #" + current).appendTo(document.body); 
     setTimeout(function() { 
      addDivs(current + 1, max, callback); 
     }, 0); 
     } 
     else { 
     callback(); 
     } 
    } 

    function display(msg) { 
     $("<p/>").html(msg).appendTo(document.body); 
    } 
    }); 

});​ 

Live example * Example with spinner graphic

Depuis que les rendements, vous pouvez voir les travaux en cours.

Vous remarquerez peut-être que le deuxième script prend plus de temps, peut-être beaucoup plus longtemps, en temps réel pour atteindre le même résultat. C'est parce que les rendements prennent du temps, tout comme le navigateur qui met à jour l'affichage. En pratique, vous aurez besoin de trouver un équilibre entre le premier exemple et le second   — quelque chose qui donne assez souvent pour montrer le progrès, mais pas si souvent que le processus prend un temps inutilement long à terminer.

+0

à quoi ressemble exactement l'appel à setTimeout? – mrjohn

+0

@mrjohn: Ajout d'un exemple avec et sans. –

+0

Point intéressant à propos de trouver le bon équilibre. Je me demande s'il est possible d'exécuter à la capacité du navigateur avant de céder pour obtenir le meilleur résultat. Un peu comme FPS dans les graphiques. –

0

Si votre méthode de longue durée effectue un appel ajax synchrone. Utilisez l'option asynchrone sur la méthode ouverte.

xmlHttp.open('POST', ajaxurl, true); 

Cela permettra à vos graphiques en rotation de tourner.