Jquery ajax beforesend
У меня есть простой вызов ajax, который выполняет функцию на beforeSend и при завершении. Они выполняются отлично, но beforeSend "кажется" не выполняется до тех пор, пока не будет успешным. При отправке отправляется уведомление "Подождите". Если я положу разрыв после функции в beforeSend, он покажет это уведомление, а затем ударит успех. Без точки останова он будет сидеть и думать, ожидая ответа, а затем, пожалуйста, подождите, пока уведомление не появится на долю секунды после успеха. Желаемая функциональность заключается в том, чтобы получить уведомление, как только запрос будет отправлен, чтобы он отображался, пока он ожидает ответа.
$.ajax({
type : 'POST',
url : url,
async : false,
data : postData,
beforeSend : function (){
$.blockUI({
fadeIn : 0,
fadeOut : 0,
showOverlay : false
});
},
success : function (returnData) {
//stuff
},
error : function (xhr, textStatus, errorThrown) {
//other stuff
},
complete : function (){
$.unblockUI();
}
});
Ответы
Ответ 1
Ваша проблема - флаг async:false
. Помимо того факта, что это плохая практика (и действительно имеет смысл только в очень ограниченном числе случаев), она фактически противоречит порядку выполнения остальной части кода. Вот почему:
Кажется, что где-то в коде blockUI
они устанавливают setTimeout
. В результате код blockUI
ждет очень короткий промежуток времени. Поскольку следующая команда в очереди - это вызов ajax()
, выполнение этого заклада blockUI
устанавливается прямо за ним. И поскольку вы используете async:false
, он должен дождаться завершения полного вызова ajax
до его запуска.
В деталях, вот что происходит:
- Вы вызываете
blockUI
-
blockUI
имеет setTimeout и запускается после истечения таймаута (даже если длина таймаута равна 0, первая строка будет ajax()
)
-
ajax()
вызывается с async:false
, что означает, что JS останавливает все, пока запрос не вернет
-
ajax()
возвращается успешно, и выполнение JS может продолжаться
- код setTimeout внутри
blockUI
, вероятно, закончился, поэтому он будет выполнен следующим образом
- он выглядит как
blockUI
работает как часть success
, но на самом деле он только что оказался в очереди из-за тайм-аута
Если вы НЕ используете async:false
, выполнение будет выполняться следующим образом:
- Вы вызываете
blockUI
-
blockUI
имеет setTimeout и запускается после истечения таймаута (даже если длина таймаута равна 0, первая строка будет ajax()
)
-
ajax()
вызывается и отправляет запрос на сервер.
- Пока он подключается к серверу, обычное выполнение JS продолжается
- код setTimeout внутри
blockUI
, вероятно, закончился, поэтому он будет выполнен следующим образом
- отображается текст
blockUI
- если там больше JS-кода, выполнение JS выполняется до тех пор, пока не будут выполнены обратные вызовы AJAX
success
и complete
Вот некоторые примеры jsFiddle для демонстрации проблемы:
Пример 1: Это та ситуация, с которой вы столкнулись. Текст blockUI
не отображается до тех пор, пока не будет выполнен вызов ajax
.
Пример 2: это та же самая ситуация, что и у вас, но с alert
перед вызовом ajax
. Поскольку существует alert
, таймаут внутри blockUI
помещает внешний вид текста blockUI
после alert
, а не после ajax
.
Пример 3: так предполагается, что он будет работать без async:false
Ответ 2
Это, скорее всего, из-за async : false
. Поскольку ваш вызов синхронный,
после того, как начнется ваш вызов функции $.ajax()
, ничего не произойдет до тех пор, пока не будет получен ответ, а следующая вещь, касающаяся вашего кода, будет обработчиком success
Чтобы он работал, вы можете сделать что-то вроде этого
$.blockUI({
fadeIn : 0,
fadeOut : 0,
showOverlay : false
});
// and here goes your synchronous ajax call
$.ajax({
type : 'POST',
url : url,
async : false,
data : postData,
success : function (returnData) {
//stuff
},
error : function (xhr, textStatus, errorThrown) {
//other stuff
},
complete : function (){
$.unblockUI();
}
});
Ответ 3
$.blockUI({
fadeIn : 0,
fadeOut : 0,
showOverlay : false
});
setTimeout(function() {
$.ajax({
type : 'POST',
url : url,
async : false,
data : postData,
success : function (returnData) {
//stuff
},
error : function (xhr, textStatus, errorThrown) {
//other stuff
}
});
},100);
$.unblockUI();
http://bugs.jquery.com/ticket/7464
Ответ 4
Другим подходом может быть функция перегрузки $.ajax
$.orig_ajax = $.ajax;
$.ajax = function() {
var settings = {async: true};
if (2 == arguments.length && 'string' == typeof arguments[0] && 'object' == typeof arguments[1])
settings = arguments[1];
else if (arguments.length && 'object' == typeof arguments[0])
settings = arguments[0];
if (!settings.async && 'function' == typeof settings.beforeSend) {
var args = arguments;
settings.beforeSend();
var dfd = $.Deferred();
setTimeout(function() {
$.orig_ajax.apply($, args).then(dfd.resolve)
.fail(dfd.reject);
} ,100);
return dfd.promise();
} else
return $.orig_ajax.apply($, arguments);
};
не совершенен (из-за другого отложенного объекта), но может быть полезным.