Как предотвратить "Прекратить запуск этого скрипта" в браузерах?
У меня есть 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
У любого был этот 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