jquery - повертає значення за допомогою результату ajax для успіху


95

У мене є невелика проблема з функцією 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 запускає "зміна", ми отримуємо деякі значення з кількох елементів для обчислень.

ми отримуємо атрибут мітки опції з нашого вибору, який зберігає значення, яке потрібно додати до загальної суми, ім'я вибору для створення сеансу з цим ім'ям та значення, щоб пізніше перевірити, який з них було вибрано.

тепер - ми перевіряємо, чи є 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');
        }
    });
}

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

Хтось знає, як повернути значення з функції, а потім порівняти її в наступному твердженні?


Дякую, хлопці - я спробував це наступним чином:

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 (дані) {результат = дані; }

результат - це глобальна змінна - яку я намагаюся прочитати:

$("#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();
    });

але чомусь - це не працює - будь-яка ідея?



Це може допомогти вирішити цю проблему: 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
}

11
Ви МОЖЕТЕ повернути значення з запиту 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

48
"Несинхронний" можна, звичайно, також називати "синхронним";)
Чарлз Вуд

в обох запропонованих вами методах; тобто. запустити функцію за допомогою успіху, тоді вам доведеться записати кілька аяксів для різних сценаріїв. це не допоможе у створенні глобальної обгортки ajax, двигуна.
wpcoder

Здається, async: false тепер застаріло і всю обробку потрібно виконати у функціях зворотного виклику.
Пунет Ламба

31

Існує багато способів отримати відповідь 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% ОК! ;)
Шальк Кеун

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;
}

Надія комусь допомагає

анакін


4
Ви насправді просто вимкніть асинхрон
Weijing Jay Lin

4

Незважаючи на те, що всі підходи щодо використання 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


3

Додайте async: falseдо списку атрибутів. Це змушує потік JavaScript чекати, поки повернеться значення повернення, перш ніж рухатися далі. Очевидно, ви б не хотіли цього робити за будь-яких обставин, але якщо знадобиться значення, перш ніж продовжувати, це зробить це.


3
Ви ніколи не повинні ставити async: false. Це блокує кожне натискання на сторінці протягом тривалості пошуку. Ви знаєте, що означає A в AJAX: Асинхронний. Правильною відповіддю було б те, що OP повинен правильно використовувати success()зворотний дзвінок
nietonfir

2
Я визнав той факт, що все треба чекати. За певних обставин викличній функції може знадобитися повернене значення, наприклад, додавання нового запису та повернення ідентифікатора запису. Коли ви знаєте правила, ви знаєте, коли вони можуть бути порушені. Ніколи не кажи ніколи. Ось хтось інший погоджується. ( stackoverflow.com/questions/3880361/… )
Hoodlum

1
@CharlesWood Виключно для тих, хто не може зрозуміти асинхронний характер аякса.
nietonfir

1
@nietonfir: якщо ви ніколи не використовуєте, async: falseчому б jQuery реалізував цю опцію? якщо я не завантажую великі обсяги даних на сторінку і просто обробляю події користувача, це нормально, що він блокує все інше за короткий проміжок часу для конкретного користувача. нічого поганого і нічого поганого в цьому. (при правильному використанні він нічого не заблокує, оскільки в цей конкретний час інші дії для конкретного користувача не відбудуться)
low_rents

1
@northkildonan Ні, це не нормально. Запит на синхронізацію AJAX поганий. Він блокує повний потік JavaScript тим, що ви не можете контролювати. Ви не маєте контролю над кількістю часу, який може знадобитися для обробки запиту: з'єднання може бути ненадійним, сервер може зайняти більше часу , ніж очікувалося, і т.д. Єдина причина , це в JQuery є те , що вам може знадобитися для збереження даних on load unload (єдине місце, яке не має значення, якщо це займе більше часу, оскільки користувач вже висловив бажання залишити сторінку). Подивіться лише на тести jQuery unit…
nietonfir

3

Це досить старе, і некрасиво, не робіть цього. Вам слід скористатися зворотними дзвінками: https://stackoverflow.com/a/5316755/591257
Була така ж проблема, вирішено її таким чином, використовуючи глобальний var. Не впевнений, що це найкраще, але, безумовно, працює. При помилці ви отримуєте порожню рядок (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;
}

3
Ви також повинні додати 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, це, мабуть, нікому не допоможе
Алон Ейтан

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.