it-swarm.com.ru

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

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

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

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.
361
Guffa

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

Смотрите это DEMO .

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

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

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

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

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

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

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

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

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

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

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

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

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 сегодня, вы можете использовать polyfill() модуля es6-обещания Джейк Арчибальд.

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

Для получения дополнительной информации см .:

Будущее jQuery

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

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

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

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

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

Больше информации

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

382
rsp

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

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

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

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

0
user1509803