3

Сейчас я использую код вида:

function getData(key, id)
{
    var data = '';
$.get(
    'http://site.com/gate.php',
    {'key': key, 'id': id, 'action': 'get'},
    function (res) {
        data = res.split('|')[1];
    }

return data;

}

Вопрос: можно ли как-то возвращать результат из замыкания передаваемого в $.get()? Что-то вроде этого:

function getData(key, id)
{
    return $.get(
        'http://site.com/gate.php',
        {'key': key, 'id': id, 'action': 'get'},
        function (res) {
            return res.split('|')[1];
        }
}
  • 1
    Через глобальные переменные можно всегда.

    А return для ajax'а вообще непонятно куда вернёт значение.

    – Vladislav Pyatkov Feb 21 '15 at 16:20
  • В данном случае будет лучше вариант с callback функцией – zhenyab Feb 21 '15 at 16:22
  • @WinterSilence У Вас запрос выполняется асинхронно, потому только через Promise – romeo Feb 21 '15 at 16:32
  • @romeo так? function getData(key, id) { var jqxhr = $.get( 'http://site.com/gate.php', {'key': key, 'id': id, 'action': 'get'} );
    return jqxhr.done(function(res) {
        return res.split('|')[1];
    });
    

    }

    – WinterSilence Feb 21 '15 at 16:48

2 Answers2

5

@Deonis всё правильно написал, но поддержка браузерами нативных Promises далека от идеала. Ждём Spartan

Существуют множество полифиллов, в том числе и для JQuery.

function getData(key, id){   
   var dfd = $.Deferred(),
       data =  {'key': key, 'id': id, 'action': 'get'};

$.get('http://site.com/gate.php', data) .done(function (response) {
response = 'foo|bar|baz'; // предположим, что response вернул такую строчку dfd.resolve(response); }) .fail(dfd.reject);

return dfd; }

getData(10, 100).then(function (response) { alert(response.split('|')[1]); }, function (error) { // обработчик ошибок });

Смотреть результат здесь

Update

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

function getData(key, id){ 
     var result;
 $.ajax({
    url: 'http://site.com/gate.php',
    type: 'GET',
    async: false,
    data: {
        key: key,
        id: id,
        action: 'get'
    },
})
.done(function(response){
    response = 'foo|bar|baz'; // предположим, что response вернул такую строчку

    result = response.split('|')[1];
})
.fail(function(){
  // обработчик ошибок
});

return result;

}

alert(getData(10, 100));

Смотреть результат здесь

romeo
  • 5,078
  • Поясню свою задачу - функция отправляет на сервер данные и получает id заявки, id передается в другую функцию, которая через некоторое время запрашивает у сервера ответ, т.е.
    var id = sendData(data); var result = loadResult(id);
    
    – WinterSilence Feb 21 '15 at 18:03
  • @WinterSilence, какой-то день сумашествия... Ну, кто вам мешает отправить данные в какую-то другую функцию? Отправляйте её хоть в десяток. – Deonis Feb 21 '15 at 18:04
  • @Deonis если вызвать loadResult(id) внутри sendData(data), то это все равно не решает проблему с возвращением результата ф-цией sendData – WinterSilence Feb 21 '15 at 18:11
  • 1
    @WinterSilence Вы должны понимать, что JS, это асинхронный язык (т.е. некоторые команды могут не дожидаться выполнения предыдущих). Интерпретатор не ждёт пока запрос завершится, а дальше выполняет указанные инструкции/команды. Я Вам привёл синхронный пример выполнения $.ajax (смотрите Update), но за такое бьют по рукам. – romeo Feb 21 '15 at 18:19
  • @romeo я это понимаю, но как решить эту задачу при асинхронном подходе, не знаю, придется все-таки использовать async: false, – WinterSilence Feb 21 '15 at 18:27
  • @WinterSilence Если совсем просто, то Вы должны все манипуляции с данными, которые поступили от сервера писать в .done(function(response){ /* обработчик данных */ }) или же обработчик данных передать в .done(success):
    var success = function (response) {
        alert(response.split('|')[1]);
    };
    
    $.ajax(...).done(success);
    
    – romeo Feb 21 '15 at 18:38
  • $.get уже возвращает промиз. Зачем использовать Deferred? – Pavel Mayorov Jul 27 '16 at 19:33
2
function getData(key, id) {
    return new Promise(function (resolve, reject) {
        $.ajax({
            url: 'http://site.com/gate.php',
            type: 'GET',
            data: {
                key: key,
                id: id,
                action: 'get'
            },
            error: reject,
            success: function (res) {
                resolve(res.split('|')[1]);
            }
        });
    });
}

getData(10, 100).then(function (response) {
    console.log("Всё гуд!", response);
}, function (error) {
    alert('Хьюстон! У нас проблемы!: ' + error.statusText);
});
Deonis
  • 34,025
  • возвращаясь к первоначальному вопросу, а так можно?
    var id = getData(10, 100).then(
        function (response) {
            return response;
        },
        function (error) {
            alert('Хьюстон! У нас проблемы!: ' + error.statusText);
        }
    );
    
    – WinterSilence Feb 21 '15 at 17:31
  • @WinterSilence Нет, нельзя, т.к. void – romeo Feb 21 '15 at 17:41
  • тогда, увы, данный вариант не приближает меня к решению проблемы. ( – WinterSilence Feb 21 '15 at 17:47
  • @WinterSilence, а вы можете описать причину, почему не подходит? Смотрите пример. Проверяете перед запросом, что содержится в переменной data, потом отправляете запрос и по его завершению опять проверяете. Значение изменилось и доступно глобально, как вроде бы вам и надо было. – Deonis Feb 21 '15 at 18:02
  • @Deonis Поясню свою задачу - функция отправляет на сервер данные и получает id заявки, id передается в другую функцию которая через некоторое время запрашивает у сервера ответ. т.е. var id = sendData(data); var result = loadResult(id); – WinterSilence Feb 21 '15 at 18:04
  • @WinterSilence, на это я уже ответил ниже. Короче, делайте синхронный запрос и будет вам счастье. Правда, счастья для юзера не будет. – Deonis Feb 21 '15 at 18:06
  • @Deonis спасибо за ответы, этот код будет использоваться в персональном плагине для FF и, кроме меня, у него потребителей не будет. ) – WinterSilence Feb 21 '15 at 18:39