Как заставить jQuery ждать завершения вызова Ajax до его возврата?

189

У меня есть функция на стороне сервера, которая требует входа. Если пользователь вошел в систему, функция вернет 1 при успешном завершении. Если нет, функция вернет страницу входа.

Я хочу вызвать функцию с помощью Ajax и jQuery. То, что я делаю, представляет запрос с помощью обычной ссылки с применением функции click-function. Если пользователь не вошел в систему или функция не работает, я хочу, чтобы Ajax-call возвращал true, чтобы триггеры href.

Однако, когда я использую следующий код, функция завершается перед вызовом Ajax.

Как я могу перенаправить пользователя на страницу входа?

$(".my_link").click(
    function(){
    $.ajax({
        url: $(this).attr('href'),
        type: 'GET',
        cache: false,
        timeout: 30000,
        error: function(){
            return true;
        },
        success: function(msg){ 
            if (parseFloat(msg)){
                return false;
            } else {
                return true;
            }
        }
    });
});
  • 1
    Возможно, это старая ветка, но, как указывает @kofifus, установка асинхронного значения на false - плохой дизайн, и «никакие тайм-ауты и т.д. не будут обрабатываться». Можно попробовать это упрощенное решение - stackoverflow.com/a/11576418/6937841
Теги:

5 ответов

269
Лучший ответ

Если вы не хотите, чтобы функция $.ajax() возвращалась немедленно, установите для параметра async значение false:

$(".my_link").click(
    function(){
    $.ajax({
        url: $(this).attr('href'),
        type: 'GET',
        async: false,
        cache: false,
        timeout: 30000,
        error: function(){
            return true;
        },
        success: function(msg){ 
            if (parseFloat(msg)){
                return false;
            } else {
                return true;
            }
        }
    });
});

Но я бы отметил, что это будет противоречить точке AJAX. Кроме того, вы должны обрабатывать ответ в функциях error и success. Эти функции будут вызываться только тогда, когда ответ получен с сервера.

  • 1
    Вы имеете в виду ложь :) Я думаю?
  • 0
    Хах! Да, спасибо.
Показать ещё 12 комментариев
30

Я не использую $.ajax, а функции $.post и $.get, поэтому, если мне нужно ждать ответа, я использую это:

$.ajaxSetup({async: false});
$.get("...");
  • 0
    Это работает и для $ .getJSON () ... что имеет смысл
27

Основной объект XMLHttpRequest (используемый jQuery для запроса) поддерживает асинхронное свойство. Установите значение false. Как

async: false
15

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

Это может быть достигнуто с помощью jQuery promises следующим образом:

// same as $.ajax but settings can have a maskUI property
// if settings.maskUI==true, the UI will be blocked while ajax in progress
// if settings.maskUI is other than true, it value will be used as the color value while bloking (i.e settings.maskUI='rgba(176,176,176,0.7)'
// in addition an hourglass is displayed while ajax in progress
function ajaxMaskUI(settings) {
    function maskPageOn(color) { // color can be ie. 'rgba(176,176,176,0.7)' or 'transparent'
        var div = $('#maskPageDiv');
        if (div.length === 0) {
            $(document.body).append('<div id="maskPageDiv" style="position:fixed;width:100%;height:100%;left:0;top:0;display:none"></div>'); // create it
            div = $('#maskPageDiv');
        }
        if (div.length !== 0) {
            div[0].style.zIndex = 2147483647;
            div[0].style.backgroundColor=color;
            div[0].style.display = 'inline';
        }
    }
    function maskPageOff() {
        var div = $('#maskPageDiv');
        if (div.length !== 0) {
            div[0].style.display = 'none';
            div[0].style.zIndex = 'auto';
        }
    }
    function hourglassOn() {
        if ($('style:contains("html.hourGlass")').length < 1) $('<style>').text('html.hourGlass, html.hourGlass * { cursor: wait !important; }').appendTo('head');
        $('html').addClass('hourGlass');
    }
    function hourglassOff() {
        $('html').removeClass('hourGlass');
    }

    if (settings.maskUI===true) settings.maskUI='transparent';

    if (!!settings.maskUI) {
        maskPageOn(settings.maskUI);
        hourglassOn();
    }

    var dfd = new $.Deferred();
    $.ajax(settings)
        .fail(function(jqXHR, textStatus, errorThrown) {
            if (!!settings.maskUI) {
                maskPageOff();
                hourglassOff();
            }
            dfd.reject(jqXHR, textStatus, errorThrown);
        }).done(function(data, textStatus, jqXHR) {
            if (!!settings.maskUI) {
                maskPageOff();
                hourglassOff();
            }
            dfd.resolve(data, textStatus, jqXHR);
        });

    return dfd.promise();
}

с этим вы можете теперь:

ajaxMaskUI({
    url: url,
    maskUI: true // or try for example 'rgba(176,176,176,0.7)'
}).fail(function (jqXHR, textStatus, errorThrown) {
    console.log('error ' + textStatus);
}).done(function (data, textStatus, jqXHR) {
    console.log('success ' + JSON.stringify(data));
});

И пользовательский интерфейс будет блокироваться до тех пор, пока команда ajax не вернет

см. jsfiddle

  • 0
    Разве установка async в false не делает то же самое, кроме одной строки кода?
  • 3
    Не за что. Если для параметра async установлено значение false, запрос будет асинхронным - то есть остановка обработки до тех пор, пока он не вернется, что обычно является плохой практикой, например, никакие события, другие запросы ajax, таймауты и т. Д. Не будут обрабатываться. Вы также можете изменить приведенный выше код, чтобы заблокировать только часть пользовательского интерфейса во время обработки вашего ajax (то есть части, на которую он повлияет)
9

Я думаю, что было бы проще, если бы вы закодировали свою функцию success для загрузки соответствующей страницы вместо возврата true или false.

Например, вместо возврата true вы можете сделать:

window.location="appropriate page";

Таким образом, когда функция успеха называется страницей, перенаправляется страница.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню