jquery - возвращаемое значение с использованием результата ajax в случае успеха

96

У меня небольшая проблема с функцией jquery $ .ajax ().

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

Теперь - у меня есть одно из раскрывающихся меню, в котором есть 4 варианта - первый (с меткой None) имеет значение = "", у других их идентификаторы.

Я хочу, чтобы параметр «Нет» (с пустым значением) удалял сеанс, а другой - для его создания, но только в том случае, если сеанс с этим конкретным именем выбора еще не существует, поскольку для всех других параметров ему присвоено такое же количество - это просто указывает, какой из них был выбран.

Я не уверен, имеет ли это смысл, но взгляните на код - возможно, это прояснит:

$("#add_ons select").change(function() {
        // get current price of the addons
        var order_price_addon = $(".order_price_addon").text();
        // get price of the clicked radio button from the rel attribute
        var add = $(this).children('option').attr('label');
        var name = $(this).attr('name');
        var val = $(this).val();


        if(val == "") {
            var price = parseInt(order_price_addon) - parseInt(add);
            removeSession(name);
        } else {
            if(isSession(name) == 0) {
                var price = parseInt(order_price_addon) + parseInt(add);
            }   
            setSession(name, val);              
        }

        $(".order_price_addon").html(price);    
        setSession('order_price_addon', price);         
        updateTotal();
});

Итак - во-первых, когда триггеры меню выбора #add_ons вызывают "изменение", мы получаем некоторые значения из нескольких элементов для расчетов.

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

теперь - мы проверяем, был ли выбран параметр val == "" (который будет указывать на то, что опция None выбрана), и мы вычитаем сумму из общей суммы, а также удаляем сеанс с именем выбора.

После этого начинается проблема - оператор else.

Иначе - мы хотим проверить, возвращает ли функция isSession () с именем нашего селектора 0 или 1 - если она возвращает 0, мы добавляем к итоговому значению значение, хранящееся в атрибуте label, но если оно возвращает 1 - это предполагает этот сеанс уже существует - тогда мы изменяем значение этого сеанса только путем его воссоздания - но сумма к нему не добавляется.

Теперь функция isSession выглядит так:

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

Теперь - проблема в том, что я не знаю, вернет ли использование «return» результат функции - поскольку это, похоже, не работает - однако, если я помещу «данные» в раздел success: в предупреждение - похоже, он возвращает правильное значение.

Кто-нибудь знает, как вернуть значение из функции, а затем сравнить его в следующей инструкции?


Спасибо, ребята - пробовал следующим образом:

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            updateResult(data);
        },
        error: function() {
            alert('Error occured');
        }
    });
}

затем функция updateResult ():

функция updateResult (данные) {результат = данные; }

result - это глобальная переменная, которую я потом пытаюсь прочитать:

$("#add_ons select").change(function() {
        // get current price of the addons
        var order_price_addon = $(".order_price_addon").text();
        // get price of the clicked radio button from the rel attribute
        var add = $(this).children('option').attr('label');
        var name = $(this).attr('name');
        var val = $(this).val();


        if(val == "") {
            var price = parseInt(order_price_addon) - parseInt(add);
            removeSession(name);
        } else {
            isSession(name);
            if(result == 0) {
                var price = parseInt(order_price_addon) + parseInt(add);
            }   
            setSession(name, val);              
        }

        $(".order_price_addon").html(price);    
        setSession('order_price_addon', price);         
        updateTotal();
    });

но по какой-то причине - не работает - есть идеи?

user398341
источник
возможный дубликат Как вернуть ответ на вызов AJAX?
Берги
Это может помочь решить эту проблему: stackoverflow.com/questions/14220321/…
mirzaei.sajad

Ответы:

114

Проблема в том, что вы не можете вернуть значение из асинхронного вызова, такого как запрос AJAX, и ожидать, что оно сработает.

Причина в том, что код, ожидающий ответа, к моменту получения ответа уже выполнен.

Решение этой проблемы заключается в запуске необходимый код внутри на success:обратный вызов. Таким образом, он получает доступ dataтолько тогда, когда он доступен.

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            // Run the code here that needs
            //    to access the data returned
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

Другая возможность (которая фактически то же самое) - вызвать функцию внутри вашего success:обратного вызова, которая передает данные, когда они доступны.

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
                // Call this function on success
            someFunction( data );
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

function someFunction( data ) {
    // Do something with your data
}
user113716
источник
12
Вы МОЖЕТЕ вернуть значение из запроса AJAX, но только если вы сделаете его неасинхронным (установите этот параметр async: false). В некоторых случаях асинхронный вызов не является обязательным. Подробнее о jquery.ajax () doc api.jquery.com/jQuery.ajax , не о томAs of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated;
Adrien Be
50
«Неасинхронный», конечно, также может называться «синхронным»;)
Чарльз Вуд
в обоих предложенных вами методах; т.е. запустите функцию с успехом, тогда вам нужно будет написать несколько ajax для разных сценариев. это не поможет в создании глобальной оболочки ajax, engine.
wpcoder 03
Похоже, async: false теперь устарел, и вся обработка должна выполняться в функциях обратного вызова.
Пунит Ламба,
33

Есть много способов получить ответ jQuery AJAX. Я делюсь с вами двумя распространенными подходами:

Первый:

используйте async = false и внутри функции верните ajax-объект, а затем получите ответ ajax-object.responseText

/**
 * jQuery ajax method with async = false, to return response
 * @param  {mix}  selector - your selector
 * @return {mix}           - your ajax response/error
 */
function isSession(selector) {
    return $.ajax({
        type: "POST",
        url: '/order.html',
        data: {
            issession: 1,
            selector: selector
        },
        dataType: "html",
        async: !1,
        error: function() {
            alert("Error occured")
        }
    });
}
// global param
var selector = !0;
// get return ajax object
var ajaxObj = isSession(selector);
// store ajax response in var
var ajaxResponse = ajaxObj.responseText;
// check ajax response
console.log(ajaxResponse);
// your ajax callback function for success
ajaxObj.success(function(response) {
    alert(response);
});

Второй:

используйте метод $ .extend и создайте новую функцию, например ajax

/**
 * xResponse function
 *
 * xResponse method is made to return jQuery ajax response
 * 
 * @param  {string} url   [your url or file]
 * @param  {object} your ajax param
 * @return {mix}       [ajax response]
 */
$.extend({
    xResponse: function(url, data) {
        // local var
        var theResponse = null;
        // jQuery ajax
        $.ajax({
            url: url,
            type: 'POST',
            data: data,
            dataType: "html",
            async: false,
            success: function(respText) {
                theResponse = respText;
            }
        });
        // Return the response text
        return theResponse;
    }
});

// set ajax response in var
var xData = $.xResponse('temp.html', {issession: 1,selector: true});

// see response in console
console.log(xData);

вы можете сделать его настолько большим, насколько захотите ...

Нирадж Сингх
источник
Хорошая идея, но ajaxObj['responseText']ее не существует, когда вы определяетеvar ajaxResponse
mu3
Отлично!! Ваше первое решение спасло меня
Каллел Омар
Второй способ - 100% ОК! ;)
Schalk Keun
7
Начиная с jQuery 1.8, использование async: false устарело!
gatteo
10

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

У меня получилось сделать что-то вроде этого:

function isSession(selector) {
    //line added for the var that will have the result
    var result = false;
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        //line added to get ajax response in sync
        async: false,
        success: function(data) {
            //line added to save ajax response in var result
            result = data;
        },
        error: function() {
            alert('Error occured');
        }
    });
    //line added to return ajax response
    return result;
}

Надежда кому-то помогает

Анакин

Анакин
источник
5
На самом деле вы просто выключаете асинхронный
режим
5

Хотя все подходы, касающиеся использования async: false, не годятся из-за его устаревания и зависания страницы до тех пор, пока запрос не вернется. Таким образом, вот два способа сделать это:

1-й: вернуть весь ответ ajax в функцию, а затем использовать doneфункцию для захвата ответа, когда запрос будет завершен. (РЕКОМЕНДУЕТСЯ, НАИЛУЧШИЙ СПОСОБ)

function getAjax(url, data){
    return $.ajax({
        type: 'POST',
        url : url,              
        data: data,
        dataType: 'JSON',
        //async: true,  //NOT NEEDED
        success: function(response) {
            //Data = response;
        }
    });
 }

НАЗЫВАЙТЕ ВЫШЕ КАК:

getAjax(youUrl, yourData).done(function(response){
    console.log(response);
});

ДЛЯ НЕСКОЛЬКИХ ВЫЗОВОВ AJAX ИСПОЛЬЗУЙТЕ $.when:

$.when( getAjax(youUrl, yourData), getAjax2(yourUrl2, yourData2) ).done(function(response){
    console.log(response);
});

2-й: сохраните ответ в cookie, а затем вне вызова ajax получите это значение cookie. (НЕ РЕКОМЕНДУЕТСЯ)

        $.ajax({
            type: 'POST',
            url : url,              
            data: data,
            //async: false,    // No need to use this
            success: function(response) {
                Cookies.set(name, response);
            }
        });

        // Outside of the ajax call
        var response = Cookies.get(name);

ПРИМЕЧАНИЕ: В приведенном выше примере используется jquery cookiesбиблиотека. Она довольно легкая и работает быстро. Вот ссылка https://github.com/js-cookie/js-cookie

MR_AMDEV
источник
3

Добавьте async: falseв свой список атрибутов. Это заставляет поток javascript ждать, пока не будет получено возвращаемое значение, прежде чем двигаться дальше. Очевидно, вы не захотите делать это в любых обстоятельствах, но если значение необходимо перед продолжением, это сделает это.

Хулиган
источник
4
Никогда не садитесь async: false. Это блокирует все на странице на время поиска. Вы знаете, что означает A в AJAX: асинхронный. Правильным ответом будет то, что OP должен правильно использовать success()обратный вызов.
nietonfir 01
2
Я признал тот факт, что все должно подождать. При определенных обстоятельствах вызывающей функции может потребоваться возвращаемое значение, например, для добавления новой записи и возврата идентификатора записи. Как только вы узнаете правила, вы узнаете, когда их можно нарушить. Никогда не говори никогда. Вот еще кто-то, кто согласен. ( stackoverflow.com/questions/3880361/… )
Hoodlum
1
@CharlesWood Исключительно для тех, кто не может понять асинхронную природу ajax.
nietonfir
1
@nietonfir: если вы никогда не должны использовать async: falseэту опцию, зачем jQuery? если я не загружаю большие объемы данных на страницу и просто обрабатываю пользовательское событие, нормально, что он блокирует все остальное за короткий промежуток времени для этого конкретного пользователя. ничего плохого и ничего плохого в этом нет. (при правильном использовании он ничего не заблокирует, потому что в этот конкретный момент никаких других действий для этого конкретного пользователя не произойдет)
low_rents
1
@northkildonan Нет, это не нормально. Запрос синхронизации AJAX плохой. Он блокирует весь поток javascript чем-то, что вы не можете контролировать. У вас нет контроля над количеством времени, которое может потребоваться для обработки запроса: соединение может быть ненадежным, сервер может занять больше времени, чем ожидалось, и т. Д. Единственная причина, по которой он находится в jQuery, заключается в том, что вам может потребоваться сохранить данные при выгрузке страницы (единственное место, где действительно не важно, занимает ли это больше времени, так как пользователь уже выразил желание покинуть страницу). Просто посмотрите на юнит-тесты jQuery…
nietonfir
3

Это довольно старое и уродливое, не делайте этого. Вы должны использовать обратные вызовы: https://stackoverflow.com/a/5316755/591257
Была такая же проблема, решила ее таким образом, используя глобальную переменную. Не уверен, что это лучший вариант, но точно работает. При ошибке вы получаете пустую строку (myVar = ''), так что вы можете обрабатывать ее по мере необходимости.

var myVar = '';
function isSession(selector) {
  $.ajax({
    'type': 'POST',
    'url': '/order.html',
    'data': {
      'issession': 1,
      'selector': selector
    },
    'dataType': 'html',
    'success': function(data) {
      myVar = data;
    },
    'error': function() {
      alert('Error occured');
    }
  });
  return myVar;
}
Aesede
источник
4
вам также необходимо добавить async: falseсюда, потому что в асинхронном режиме не гарантируется, что dataбудет сохранено myVarдо myVarвозврата.
low_rents
2
// Common ajax caller
function AjaxCall(url,successfunction){
  var targetUrl=url;
  $.ajax({
    'url': targetUrl,
    'type': 'GET',
    'dataType': 'json',
    'success': successfunction,
    'error': function() {
      alert("error");
    }
  });
}

// Calling Ajax
$(document).ready(function() {
  AjaxCall("productData.txt",ajaxSuccessFunction);
});

// Function details of success function
function ajaxSuccessFunction(d){
  alert(d.Pioneer.Product[0].category);
}

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

Бинсон
источник
1

С помощью отсюда

function get_result(some_value) {
   var ret_val = {};
   $.ajax({
       url: '/some/url/to/fetch/from',
       type: 'GET',
       data: {'some_key': some_value},
       async: false,
       dataType: 'json'
   }).done(function (response) {
       ret_val = response;
   }).fail(function (jqXHR, textStatus, errorThrown) {
           ret_val = null;
       });
   return ret_val;
}

Надеюсь, это поможет кому-то немного.

Мухаммад Нахид
источник
Использование async: false,является доисторическим и устарело с jQuery v1.8. Вероятно, это никому не поможет
Алон Эйтан
-2

Привет, попробуйте async: false в вашем вызове ajax ..

Катир
источник