jQuery: возврат данных после успешного вызова ajax [дубликат]

этот вопрос уже есть ответ здесь:

у меня есть что-то вроде этого, где это простой вызов скрипта, который возвращает мне значение, строку..

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {
         return data; 
      }
   });
}

но если я называю что-то вроде это

var output = testAjax(svar);  // output will be undefined...

так как я могу вернуть значение? приведенный ниже код, похоже, тоже не работает...

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {

      }
   });
   return data; 
}

5 ответов


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

Вы можете передать в функцию обратного вызова, которая обрабатывает результат:

function testAjax(handleData) {
  $.ajax({
    url:"getvalue.php",  
    success:function(data) {
      handleData(data); 
    }
  });
}

назовем это так:

testAjax(function(output){
  // here you use the output
});
// Note: the call won't wait for the result,
// so it will continue with the code here while waiting.

Примечание: этот ответ был написан в феврале 2010 года.
см. обновления от 2015, 2016 и 2017 в нижней части.

вы не можете ничего возвращать из функции, которая является асинхронной. Что вы можете вернуть это обещание. Я объяснил, как обещания работают в jQuery в моих ответах на эти вопросы:

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

вообще, вместо:

function testAjax() {
  $.ajax({
    url: "getvalue.php",  
    success: function(data) {
      return data; 
    }
  });
}

вы можете написать свою функцию testAjax следующим образом:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

тогда вы можете получить свое обещание так:

var promise = testAjax();

вы можете хранить ваше обещание, вы можете передать его, вы можете использовать его в качестве аргумента в вызовах функций, и вы можете вернуть его из функций, но когда Вы наконец захотите использовать ваши данные, возвращаемые вызовом AJAX, вы должны сделать это следующим образом:

promise.success(function (data) {
  alert(data);
});

(упрощенный синтаксис см. В разделе Обновления ниже.)

если ваши данные доступны на данный момент, то эта функция будет вызвана немедленно. Если это не так, то он будет вызван, как только данные имеются.

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

посмотреть этот демо.

обновление (2015)

в настоящее время (по состоянию на март 2015 года) обещания jQuery несовместимы с обещания/а+ спецификация что означает, что они не могут очень хорошо сотрудничать с другими обещания / a + соответствующие реализации.

однако jQuery обещает в предстоящей версии 3.x будет совместимо с спецификацией Promises / A+ (спасибо Бенджамин Gruenbaum для указания). В настоящее время (по состоянию на май 2015 года) стабильными версиями jQuery являются 1.x и 2.x.

то, что я объяснил выше (в марте 2011 года), - это способ использования отложенные объекты jQuery сделать что-то асинхронно, что в синхронном коде было бы достигнуто путем возврата значения.

но синхронный вызов функции может делать две вещи - он может либо возвращать значение (если он может), либо вызывать исключение (если он не может возвращать значение.) Promises / A+ адресует оба этих варианта использования таким образом, что это почти так же эффективно, как обработка исключений в синхронном коде. Версия jQuery обрабатывает эквивалент возврата значения просто отлично, но эквивалент сложной обработки исключений несколько проблематичен.

в частности, весь смысл обработки исключений в синхронном коде заключается не только в отказе от хорошего сообщения, но и в попытке устранить проблему и продолжить выполнение, или, возможно переосмысление того же или другого исключения для некоторых других частей программы для обработки. В синхронном коде у вас есть стек вызовов. В асинхронном вызове вы этого не делаете, и расширенная обработка исключений внутри ваших обещаний, как того требует спецификация Promises/A+, действительно может помочь вам написать код, который будет обрабатывать ошибки и исключения значимым образом даже для сложных случаев использования.

для различий между jQuery и другими реализациями, а также Как конвертировать jQuery обещания к обещаниям/совместимый+, см. из jQuery Крис Коваль и соавт. на вики библиотеки Q и обещания поступают в JavaScript Джейк Арчибальд на HTML5 Rocks.

как вернуть реальное обещание

функция из моего примера выше:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

возвращает объект jqXHR, который является jQuery Отложенный Объект.

чтобы получить реальное обещание, вы можете изменить его на - через метод из Q wiki:

function testAjax() {
  return Q($.ajax({
      url: "getvalue.php"
  }));
}

или метод из статьи HTML5 Rocks:

function testAjax() {
  return Promise.resolve($.ajax({
      url: "getvalue.php"
  }));
}

этой Promise.resolve($.ajax(...)) что это пояснил, в promise документацию и он должен работать с ЕС6 Promise.resolve().

чтобы использовать ES6 обещания сегодня вы можете использовать es6-модуль обещания polyfill() Джейк Арчибальд.

чтобы увидеть, где вы можно использовать обещания ES6 без заполнения, см.:могу ли я использовать: обещания.

подробнее см.:

будущее jQuery

будущее версии jQuery (начиная с 3.Х - текущие стабильные версии по состоянию на май 2015 года 1.x и 2.x) будет совместим с обещания/а+ спецификация (спасибо Бенджамин Gruenbaum для указания на это в комментариях). " два изменения, которые мы уже решили, - это совместимость Promise/A+ для нашей отложенной реализации [...]" (в jQuery 3.0 и будущее веб-разработки). Для получения дополнительной информации см.:в jQuery 3.0: в Следующие Поколения!--40--> Дэйв Метвин и jQuery 3.0: больше совместимости, меньше Internet Explorer пол криля.

интересные переговоры

обновление (2016)

есть новый синтаксис ECMA-262, 6-е издание, раздел 14.2 под названием функции стрелочку это может быть использовано для дальнейшего упрощения приведенных выше примеров.

использование API jQuery вместо:

promise.success(function (data) {
  alert(data);
});

вы можете написать:

promise.success(data => alert(data));

или с помощью Promises / A + API:

promise.then(data => alert(data));

не забудьте всегда использовать обработчики отклонения либо с:

promise.then(data => alert(data), error => alert(error));

или:

promise.then(data => alert(data)).catch(error => alert(error));

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

конечно, в этом примере вы можете использовать только promise.then(alert) потому что ты просто называешь alert С теми же аргументами, что и ваш обратный вызов, но синтаксис стрелки более общий и позволяет писать вещи например:

promise.then(data => alert("x is " + data.x));

не каждый браузер поддерживает этот синтаксис, но есть определенные случаи, когда вы уверены, какой браузер ваш код будет работать - например, при написании расширение для Chrome, a Firefox дополнения, или настольное приложение с использованием Electron, NW.js или AppJS (см. ответ для деталей).

для поддержки функций стрелки, см.:

обновление (2017)

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

functionReturningPromise()
    .then(data => console.log('Data:', data))
    .catch(error => console.log('Error:', error));

можно написать:

try {
    let data = await functionReturningPromise();
    console.log('Data:', data);
} catch (error) {
    console.log('Error:', error);
}

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

для поддержки в браузерах, см.:

для поддержки в узел, см.:

в местах, где у вас нет родной поддержки async и await вы можете использовать Babel:

или с немного другим синтаксисом подход на основе генератора, как в co или Bluebird coroutines:

Подробнее

некоторые другие вопросы о обещаниях для более подробной информации:


вы можете добавить опцию async в false и возврат вне вызова ajax.

function testAjax() {
    var result="";
    $.ajax({
      url:"getvalue.php",
      async: false,  
      success:function(data) {
         result = data; 
      }
   });
   return result;
}

Idk, если вы, ребята, решили это, но я рекомендую другой способ сделать это, и он работает:)

    ServiceUtil = ig.Class.extend({
        base_url : 'someurl',

        sendRequest: function(request)
        {
            var url = this.base_url + request;
            var requestVar = new XMLHttpRequest();
            dataGet = false;

            $.ajax({
                url: url,
                async: false,
                type: "get",
                success: function(data){
                    ServiceUtil.objDataReturned = data;
                }
            });
            return ServiceUtil.objDataReturned;                
        }
    })

Итак, основная идея здесь заключается в том, что, добавив async: false, вы заставляете все ждать, пока данные не будут получены. Затем вы назначаете его статической переменной класса, и все волшебным образом работает:)


см. пример jQuery docs: http://api.jquery.com/jQuery.ajax/ (около 2/3 страницы)

вы можете искать следующий код:

    $.ajax({
     url: 'ajax/test.html',
     success: function(data) {
     $('.result').html(data);
     alert('Load was performed.');
   }
});

та же страница...опустите вниз.