Я загружаю электронную таблицу для импорта данных в мою базу данных, и перед их вставкой я запускаю проверку на стороне сервера на каждое значение.jquery ждать завершения анимации до завершения ajax
Я использую JQuery Ajax, чтобы загрузить файл на сервер, и я получаю ответ обратно из обработанных данных в виде многомерного массива
var errored = false;
var items = [];
var width;
var percent;
$("#uploadForm").ajaxForm({
dataType: 'json',
beforeSubmit: function() {
errored = false;
width = 0;
percent = 0;
},
beforeSend: function() { //before sending form
$('#upload-progress').show();
},
uploadProgress: function(event, position, total, percentComplete) { //on progress
$('#load').width(percentComplete + '%') //update progressbar percent complete
$('#load').html(percentComplete + '%'); //update status text
},
success: function(response) {
var size = Object.keys(response.items).length + 1;
//this will trigger the first callback.
var base = $.when({});
var promises = [];
percent = 100/Object.keys(response.items).length;
$('#validate-progress').show();
$('#UploadButton').html('<i class="fa fa-cog fa-spin fa-fw"></i> Validating Data');
$.each(response.items, function(key, item) {
var last = (key == size) ? true : false;
promises.push(base = base.then(getAjaxDeferred(key, item, last)));
});
},
complete: function() {
$('#load').width('0%'); //update progressbar percent complete
$('#upload-progress').hide();
$(this).clearForm();
}
});
я затем цикл через каждый из каждой строки массив и передать это функции jquery, которая использует ajax и откладывает ее до тех пор, пока она не завершится до отправки следующей строки.
function getAjaxDeferred(row, item, last) {
return function() {
// wrap with a deferred
var defer = $.Deferred();
$.ajax({
url: 'path/to/file',
method: 'POST',
data: {
row: row,
item: item
},
dataType: 'json',
success: function(response) {
$('<p>' + response.description + ' <i class="fa fa-check"></i></p>').appendTo('#inserted-rows');
items.push(response.item);
if(last) {
$('<p class="last-insert">All done!!</p>').appendTo('#inserted-rows');
if(errored) {
$('#myModal-errors').modal('show');
}
}
width = width + percent;
$('#validating').width(width + '%').html((Math.round(width * 10)/10).toFixed(0) + '%');
$('#inserted-rows').show().animate({ scrollTop: $('#inserted-rows').prop("scrollHeight") - $('#inserted-rows').height() }, 'fast');
},
complete: function() {
// resolve when complete always. Even on failure we
// want to keep going with other requests
defer.resolve();
}
});
// return a promise so that we can chain properly in the each
return defer.promise();
};
}
Все работает точно так, как я хочу на моем сервере развития (потому что это гораздо медленнее, чем производство), строка передается функции, он проверяет на сервере, добавляет ответ на выходной DIV, обновляет прогресс ширина штриха на процент и если это последняя строка, будет отображаться модальный, если будут найдены какие-либо ошибки.
Проблема, с которой я сталкиваюсь на производственном сервере, состоит в том, что она настолько быстрая, что индикатор выполнения обновляется быстрее, чем анимация, поэтому он завершается сразу, и модальная информация появляется до завершения анимации.
Я попытался добавить полную функцию function() к анимации, которая прекратила появление модальности до тех пор, пока последняя строка не будет обработана, но это не помогло обновить индикатор выполнения.
Как я могу задержать индикатор выполнения, чтобы дождаться окончания анимации до обновления ширины, а также сделать модальное ожидание до тех пор, пока последняя строка не будет обработана?
Попробуйте поместить 'defer.resolve()' в обратный вызов 'animate()' –
Попробуйте ['stop (false, true)'] (https://api.jquery.com/stop/) перед 'animate() ':' $ ('# insert-rows'). show(). stop (false, true) .animate ({... '. Это завершает текущую анимацию непосредственно перед началом следующего. –
' response. У элементов есть числовые ключи. Может быть, это массив, а не объект? –