jQuery: возвращать данные после успешного вызова ajax

353

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

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 ответов

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

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

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

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.
  • 0
    Я полагаю, что добавление статуса [success] задержит некоторые и более точные вызовы только тогда, когда статус 400 успешен.
  • 0
    @iamsirjayesh Я сделаю для тебя математику, всего 5,5 лет! ... однако полезный ответ.
Показать ещё 3 комментария
322

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

Вы не можете вернуть ничего из функции, которая является асинхронной. То, что вы можете вернуть, - это обещание. Я объяснил, как promises работает в 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, потому что он асинхронен. promises - хорошая абстракция для функций: я не могу вернуть вам данные, потому что у меня ее еще нет, и я не хочу блокировать и заставлять вас ждать, так что вместо этого вы обещаете, и вы будете возможно использовать его позже или просто передать его кому-то другому и сделать с ним.

Смотрите DEMO.

ОБНОВЛЕНИЕ (2015)

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

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

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

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

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

Для различий между jQuery и другими реализациями и как преобразовать jQuery promises в Promises/A +, см. Из jQuery Крисом Ковалем и др. на вики-библиотеке Q и Promises приходят в JavaScript Джейком Арчибальдом на скалах HTML5.

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

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

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и он должен работать с ES6 Promise.resolve().

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

Чтобы узнать, где вы можете использовать ES6 promises без polyfill, см. Могу ли я использовать: Promises.

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

Будущее jQuery

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

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

ОБНОВЛЕНИЕ (2016)

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

Использование jQuery API, а не:

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

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

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

или используя API Promises/A +:

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

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

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

или с помощью:

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

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

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

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

Не все браузеры поддерживают этот синтаксис, но есть определенные случаи, когда вы уверены, в каком браузере будет работать ваш код - например, при написании расширения Chrome, Firefox Add-on, или настольное приложение, использующее 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. Для получения дополнительной информации см.:

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

Для поддержки в Node см.

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

или со слегка отличающимся синтаксисом, основанным на генераторе, как в co или сопрограмме Bluebird:

Подробнее

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

  • 0
    Они просто возятся с ajax, видят, как это работает.
  • 6
    Идеальный ответ! Просто добавьте примечание для пользователей, это не будет работать с JQuery версии 1.4.
Показать ещё 7 комментариев
132

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

function testAjax() {
    var result="";
    $.ajax({
      url:"getvalue.php",
      async: false,  
      success:function(data) {
         result = data; 
      }
   });
   return result;
}
  • 13
    Ваше решение совершенно правильно. Я просто хочу подчеркнуть важность того, чтобы не возвращать значение сразу в обратном вызове успеха, а вне вызова функции .ajax. В противном случае вы получите неопределенное.
  • 0
    Есть ли способ использовать эту функцию с async: true?
Показать ещё 5 комментариев
0

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, вы делаете все до тех пор, пока данные не будут восстановлены. Затем вы назначаете его статической переменной класса, и все магически работает:)

  • 7
    Это уже было предложено в этом ответе ( stackoverflow.com/a/7891780/218196 ). В общем, создание синхронных Ajax-запросов не очень хорошая идея.
-10

См. пример 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.');
   }
});

Те же страницы... ниже.

Ещё вопросы

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