Как предотвратить "Прекратить запуск этого скрипта" в браузерах?

У меня есть ASP.NET MVC страница с JQuery Editable Datatable, которая имеет 14 столбцов. У меня есть кнопка (Применить без результатов), чтобы выполнить вычисления на стороне клиента и применить для всех строк в этой таблице.

Когда мы нажимаем на эту кнопку, после применения вычислений для каждых 4 строк, она отображает это сообщение "Stop Running Script".

Я проверил настройки. В окне "Свойства обозревателя" на вкладке "Дополнительно" установлен флажок "Отключить отладку сценариев (Internet Explorer)". А "Отображать уведомление об ошибке скрипта" не отмечено.

Я использую Internet Explorer 8. Теперь это не происходит на IE9. Но так как это сервер, мы не можем перейти на IE9.

Я провел исследование и попробовал эти два варианта, но ничего не получилось.

Пример (1): http://www.codeproject.com/Tips/406739/Preventing-Stop-running-this-script-in-Browsers

Пример (2): http://www.picnet.com.au/blogs/guido/post/2010/03/04/how-to-prevent-stop-running-this-script-message-in-browsers/

У любого был этот isse, и любые предложения высоко ценятся.

Это фактический код, который выдает сообщение сценария:

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();

Ссылаясь на пример кода в Примере (2), я изменил код, как показано ниже, и все еще получаю сообщение Script:

// Эта функция позволяет избежать запуска скрипта

  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();

}

Что я здесь не так делаю?

3 ответа

Решение

Проблема в том, что javascript является однопоточным, поэтому, если есть функция, выполнение которой занимает слишком много времени, пользовательский интерфейс может не отвечать. Поэтому браузер предупредит пользователя о долгосрочном скрипте, отображая сообщение: "Прекратите запуск этого скрипта". Решения этой проблемы:

  • Оптимизируйте свой код, чтобы функция не заняла так много времени.
  • использование setTimeout разбить выполнение функции на множество достаточно коротких частей.

Пример шаблона кода:

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);

Решение, которое вы принимаете в своем примере (2), является правильным, но в вашем коде есть проблема. Вот и setTimeout не запускается. Попробуйте изменить свой код следующим образом:

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, [])         
       }    
    };   
  };

Изменить ваш function ApplyNoFindings(), попробуй это:

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

вместо:

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

Примечание: не тестировалось, просто дать вам представление о том, как это должно работать

Несмотря на уже принятый другой ответ, я хочу разместить здесь общую информацию для разработчиков, у которых будет эта проблема:

По этой ссылке вы можете найти информацию о том, как это исправить, на стороне пользователя http://support.microsoft.com/kb/175500 - пользователь может добавить один ключ реестра.

Также вы можете найти там информацию о том, когда появляется это сообщение "Медленная работа":

По умолчанию ключ не существует. Если ключ не был добавлен, пороговое ограничение по умолчанию для диалогового окна времени ожидания составляет 5 000 000 операторов для Internet Explorer 4 и более поздних версий.

Как видите, медлительность измеряется в выражениях javascript, а не во времени.

Вы также можете рассмотреть HTML 5 работников

Веб-работник - это JavaScript, работающий в фоновом режиме, не влияющий на производительность страницы. При выполнении сценариев на HTML-странице страница перестает отвечать на запросы, пока сценарий не будет завершен. Веб-работник - это JavaScript, который работает в фоновом режиме, независимо от других скриптов, не влияя на производительность страницы.

Создать нового работника просто. Все, что вам нужно сделать, это вызвать конструктор Worker(), указав URI сценария для выполнения в рабочем потоке, установить для свойства Worker.onmessage соответствующего работника соответствующую функцию-обработчик событий.

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

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

В качестве альтернативы вы можете использовать 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.

Вы можете увидеть более подробную информацию по адресу: https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers

Другие вопросы по тегам