web-dev-qa-db-fra.com

Comment empêcher "Arrêtez d'exécuter ce script" dans les navigateurs?

J'ai une page ASP.NET MVC avec JQuery Editable Datatable qui comporte 14 colonnes. J'ai un bouton (Appliquer aucun résultat) pour effectuer des calculs et des applications côté client qui s'appliquent à toutes les lignes de ce tableau.

Lorsque nous cliquons sur ce bouton, après avoir appliqué les calculs pour toutes les 4 lignes, le message "Arrêter l'exécution du script" s'affiche.

J'ai vérifié les paramètres. Dans les Options Internet, onglet Avancé, l'option "Désactiver le débogage de script (Internet Explorer)" est cochée. Et "Afficher une notification concernant une erreur de script" est décoché.

J'utilise Internet Explorer 8. Maintenant, cela ne se produit pas sur IE9. Mais ceci étant le serveur, nous ne pouvons pas passer à IE9.

J'ai fait la recherche et essayé ces deux options et rien n'a fonctionné.

Exemple (1): http://www.codeproject.com/Tips/406739/Preventing-Stop-running-this-script-in-Browsers

Exemple (2): http://www.picnet.com.au/blogs/guido/post/2010/03/04/how-to-prevent-stop-running-this-script -message-in-navigateurs/

Tout le monde avait cette isse et toutes les suggestions sont très appréciées.

Ceci est le code qui envoie le message de script:

for(i < iTotalRecords;i++) 
      {  

            var row = oTableAuditLines.fnGetData(i); 
            oTableAuditLines.fnUpdate("NF",i,1); 
            UndoHCPCS(row,i);
            UndoHCPCSModCodes(row,i);
            UndoLineUnitCount(row,i);
            oTableAuditLines.fnUpdate("", i, 6); //Reset Denial Reason Code
            UndoNonCoveredCharges(row,i);
            CalculateAmountPaidAtLine(row,i);
            CalculateEstimatedRecoveryAmountAtLine(row,i);
      }
      UpdateSummaryLine();
      UpdateSummaryLineReasonCode();

En faisant référence à l'exemple de code de l'exemple (2), j'ai modifié le code comme ci-dessous et je reçois toujours le message de script:

// Cette fonction est d'éviter le script en cours d'exécution Message

  RepeatingOperation = function(op, yieldEveryIteration) 
  {  
  var count = 0;  
  var instance = this;  
  this.step = function(args) 
  {    
  if (++count >= yieldEveryIteration) 
  {      
  count = 0;      
  setTimeout(function() { op(args); }, 1, [])      
  return;      
  }    
  op(args);  
  };
  };

  function ApplyNoFindings()
  {

    var i = 0;
    var ro = new RepeatingOperation(function() 
     {  

     var row = oTableAuditLines.fnGetData(i); 
            oTableAuditLines.fnUpdate("NF",i,1); 
            UndoHCPCS(row,i);
            UndoHCPCSModCodes(row,i);
            UndoLineUnitCount(row,i);
            oTableAuditLines.fnUpdate("", i, 6); //Reset Denial Reason Code
            UndoNonCoveredCharges(row,i);
            CalculateAmountPaidAtLine(row,i);
            CalculateEstimatedRecoveryAmountAtLine(row,i);

     if (++i < iTotalRecords) 
     { 
        ro.step(); 
     }  
     else 
     { 
        UpdateSummaryLine();
        UpdateSummaryLineReasonCode();
     }  
     }, 100);
     ro.step();

}

Qu'est-ce que je fais mal ici?

8
Rita

Le problème est que javascript est à thread unique, donc s'il existe une fonction que prend trop de temps à compléter , cette fonction peut empêcher l'interface utilisateur de répondre. Par conséquent, le navigateur avertira l'utilisateur de la longue exécution du script en affichant le message: "Arrêter l'exécution de ce script" . Les solutions à ce problème sont:

  • Optimisez votre code pour que la fonction ne prenne pas si longtemps.
  • Utilisez setTimeout pour diviser l'exécution de la fonction en plusieurs parties suffisamment courtes.

Exemple de modèle de code:

var array = []; //assume that this is a very big array
var divideInto = 4;
var chunkSize = rowCount/divideInto;
var iteration = 0;

setTimeout(function doStuff(){
  var base = chunkSize * iteration;
  var To = Math.min(base+chunkSize,array.length);
  while (base < To ){
      //process array[base]
      base++;
  }
  iteration++;
  if (iteration < divideInto)
      setTimeout(doStuff,0); //schedule for next phase
},0);

La solution que vous prenez dans votre exemple (2) est correcte, mais il y a un problème dans votre code. C'est le setTimeout ne s'exécute pas . Essayez de changer votre code comme ceci:

RepeatingOperation = function(op, yieldEveryIteration) 
  {  
  var count = 0;  
  var instance = this;  
  this.step = function(args) 
    {    
       op(args); 
       if (++count <= yieldEveryIteration) 
       {          
         setTimeout(function() { instance.step(args); }, 1, [])         
       }    
    };   
  };

Modifiez votre function ApplyNoFindings(), essayez ceci:

if (++i > iTotalRecords) 
 { 
    UpdateSummaryLine();
    UpdateSummaryLineReasonCode();
 }  

au lieu de:

if (++i < iTotalRecords) 
     { 
        ro.step(); 
     }  
     else 
     { 
        UpdateSummaryLine();
        UpdateSummaryLineReasonCode();
     }  

Remarque: non testé, donnez-vous une idée du fonctionnement

11
Khanh TO

Malgré une autre réponse déjà acceptée, je souhaite placer ici des informations générales pour les développeurs qui auront ce problème dans leur fonctionnalité:

Par ce lien, vous pouvez trouver des informations sur la façon de résoudre ce problème côté utilisateur http://support.Microsoft.com/kb/175500 - utilisateur peut ajouter une clé de registre.

Vous pouvez également y trouver des informations sur le moment où le message "Running slow" apparaît:

Par défaut, la clé n'existe pas. Si la clé n'a pas été ajoutée, la limite de seuil par défaut pour la boîte de dialogue de délai d'attente est 5 000 000 instructions pour Internet Explorer 4 et les versions ultérieures.

Comme vous voyez la lenteur mesurée dans les déclarations javascript, pas dans le temps.

4
nahab

Vous pouvez également considérer les travailleurs HTML 5

Un travailleur Web est un JavaScript qui s'exécute en arrière-plan, sans affecter les performances de la page. Lors de l'exécution de scripts dans une page HTML, la page ne répond plus jusqu'à la fin du script. Un travailleur Web est un code JavaScript qui s'exécute en arrière-plan, indépendamment des autres scripts, sans affecter les performances de la page. 

Créer un nouveau travailleur est simple. Tout ce que vous avez à faire est d'appeler le constructeur Worker (), en spécifiant l'URI du script à exécuter dans le thread de travail, en définissant la propriété Worker.onmessage du travailleur sur une fonction de gestionnaire d'événements appropriée.

var myWorker = new Worker("my_task.js");

myWorker.onmessage = function (oEvent) {
  console.log("Called back by the worker!\n");
};

Vous pouvez également utiliser addEventListener ():

var myWorker = new Worker("my_task.js");

myWorker.addEventListener("message", function (oEvent) {
  console.log("Called back by the worker!\n");
}, false);

myWorker.postMessage(""); // start the worker.

Vous pouvez voir plus de détails sur: https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers

0
Steven Lizarazo