2016-07-30 4 views
1

мне нужно делать противоположное этому сообщению, «Best way to iterate over an array without blocking the UI»Как заблокировать пользовательский интерфейс для длительных цикла Javascript

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

Javascript ниже.

// toolbar events/actions 
changeZeroDiscountButton.click(function (event) { 
    var value = discountComboBox.jqxComboBox('val'); 

    if ((value != null) && (value != "")) { 
     value = value/100; 

     // get all the rows (this may have to be changed if we have paging 
     var datainformations = $('#jqxgrid').jqxGrid('getdatainformation'); 
     var rowscounts = datainformations.rowscount; 

     for (var i = 0; i < rowscounts; i++) { 
      var preSetDiscount = $("#jqxgrid").jqxGrid('getcellvalue', i, "discount"); 

      if (preSetDiscount == .0000) { 
       $("#jqxgrid").jqxGrid('setcellvalue', i, "discount", value); 
      } 
     } 
    } 

}); 
+0

Вы используете бутстрап? – jonju

+0

Сорта. Это часть компонента Joomla, а Joomla поддерживает некоторые функции Bootstrap. – NJA

ответ

0

JavaScript разработан таким образом, что не блокирует пользовательский интерфейс в любом случае, и это одна из самых важных характеристик для браузеры. Единственными исключениями являются окна всплывающих сообщений (то есть alert(), confirm() и propmpt()). Даже если это возможно, крайне не рекомендуется блокировать пользовательский интерфейс.

Существует множество альтернативных способов предотвращения действий пользователя, которые не должны срабатывать, пока не произойдет что-то еще. Примеры:

  • Отключите кнопку действия до завершения обработки, затем включите ее.
  • Установите флаг (например, var processing = true) и отметьте этот флаг в событии клика кнопки действия, чтобы он отображал сообщение (например, «все еще обрабатывать, пожалуйста, подождите ...»), когда флаг равен true и выполните действие, когда флаг есть false. Не забудьте использовать сообщение alert(), иначе вы заблокируете обработку. Вместо этого используйте всплывающее окно div.
  • Установите обработчик события в начале обработки функции, которая отображает сообщение (например, «все еще обрабатывается, пожалуйста, подождите ...») и в конце обработки установите обработчик события в функцию, которая будет выполните действие. Не забудьте использовать сообщение alert(), иначе вы заблокируете обработку. Вместо этого используйте всплывающее окно div.
  • Показывать модальное всплывающее окно div в начале обработки с сообщением (например, «обработка по-прежнему, подождите ...») или индикатор выполнения или анимацию. Модальное всплывающее окно не позволяет пользователю взаимодействовать со страницей, чтобы они не могли ничего щелкнуть. Для этого для модального всплывающего окна не должно быть кнопки закрытия или любого другого способа закрыть его. В конце обработки закройте модальное всплывающее окно, чтобы пользователь мог продолжить.

Важного примечание: Вы упомянули в своем комментарии к другому ответу, что наложение (который похож на модальное всплывающее окно в моей последней точке) не отображается до конца обработки. Это потому, что ваша обработка занимает процессор и не позволяет ему обрабатывать поток пользовательского интерфейса. Когда вы можете сделать это, задержка обработки. Итак, сначала покажите модальное всплывающее окно (или наложение), затем используйте setTimeout(), чтобы начать обработку через 1 секунду (возможно, 500 миллисекунд или даже меньше). Это дает процессору достаточно времени для обработки потока пользовательского интерфейса, прежде чем он начнет длительную обработку.

Редактировать Ниже приведен пример последнего метода:

function start() { 
 
    disableUI(); 
 
    setTimeout(function() { 
 
    process(); 
 
    }, 1000); 
 
} 
 

 
function process() { 
 
    var s = (new Date()).getTime(); 
 
    var x = {}; 
 
    for (var i = 0; i < 99999; i++) { 
 
    x["x" + i] = i * i + i; 
 
    } 
 
    var e = new Date().getTime(); 
 
    $("#results").text("Execution time: " + (e - s)); 
 
    enableUI(); 
 
} 
 

 
function disableUI() { 
 
    $("#uiOverlay").dialog({ 
 
    modal: true, 
 
    closeOnEscape: false, 
 
    dialogClass: "dialog-no-close", 
 
    }); 
 
} 
 

 
function enableUI() { 
 
    $("#uiOverlay").dialog("close"); 
 
}
.dialog-no-close .ui-dialog-titlebar { 
 
    display: none; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css"> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script> 
 

 
<button type="button" onclick="start()">Start</button> 
 
<div id="results"></div> 
 
<div id="uiOverlay" style="display: none;">Processing... Please wait...</div>

Редактировать 2 Ниже приведен пример третьего способа:

$("#StartButton").on("click", start); 
 

 
function start() { 
 
    //remove all previous click events 
 
    $("#StartButton").off("click"); 
 
    //set the click event to show the message 
 
    $("#StartButton").on("click", showProcessingMsg); 
 
    //clear the previous results 
 
    $("#results").text(""); 
 
    setTimeout(function() { 
 
    process(); 
 
    }, 1000); 
 
} 
 

 
function process() { 
 
    var s = (new Date()).getTime(); 
 
    var x = {}; 
 
    for (var i = 0; i < 99999; i++) { 
 
    x["x" + i] = i * i + i; 
 
    } 
 
    var e = new Date().getTime(); 
 
    $("#results").text("Execution time: " + (e - s)); 
 

 
    //remove all previous click events 
 
    $("#StartButton").off("click"); 
 
    //set the click event back to original 
 
    $("#StartButton").on("click", start); 
 
} 
 

 
function showProcessingMsg() { 
 
    $("#results").text("Still processing, please wait..."); 
 
}
.dialog-no-close .ui-dialog-titlebar { 
 
    display: none; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<button type="button" id="StartButton">Start</button> 
 
<div id="results"></div>

+0

Racil, у вас есть пример третьего решения, на которое вы можете указать мне? Хотя последнее решение кажется самым простым, независимо от того, что я делаю, я не могу заставить div показать перед началом обработки. – NJA

+0

Я добавил пример для вас о том, как это сделать в четвертом методе (наложение пользовательского интерфейса). Если вы все еще используете пример третьего метода, дайте мне знать. –

+0

Признак третьего метода был бы весьма полезен. на самом деле заставить метод наложения работать, поэтому я использую SweetAlert2, который, как вы указываете, является предупреждением и специально предназначен для блокировки пользовательского интерфейса. – NJA

0

Если это браузер с длинным циклом, он заблокирует все другие события. Вы можете просто воспользоваться браузером замораживания.

Это не будет хорошим опытом.

Вы можете посмотреть покрыть интерфейс с Overlay, как это и информирует пользователя о работе

+0

Я добавил функцию OpenNav() в начало моего кода, но наложение не показывается до тех пор, пока * после окончания обработки оригинального javascript.
'changeZeroDiscountButton.click (функция (событие) { openNav(); значение вар = discountComboBox.jqxComboBox ('Вал');! если ((значение = NULL) && (значение = "")) { ' – NJA