2010-04-13 3 views
1

У меня проблема с вызовом jQuery ajax. Мне нужно дождаться завершения вызова, чтобы вернуть значение. Однако сценарий, кажется, продвигается вперед и не дожидается завершения вызова. моя функция затем возвращает «undefined».jQuery wait for ajax call over over

Я попытался использовать метод .ajax() и установить значение async равным false, но это тоже не сработает.

Я могу получить свою функцию, чтобы вернуть значение, которое я мог бы выполнить через вызов ajax?

Спасибо!

Вот код:

function get_rsrce_name(){ 

    jQuery.post(

     '<?php echo admin_url('admin-ajax.php'); ?>', 

     { action :'my_action', option_rsrce : 'option_rsrce' }, 

     function(data) { 

      output = data.option_name;   

     }, 

     "json" 
    );  

    return output; 
} 
+0

Похожие на SO: http://stackoverflow.com/questions/2956261/got-stuck-in-the-asynchronous-nature-of-ajax -requests –

ответ

2

Причина, по которой не работает, когда вы говорите ему работать синхронно, что переменная «выход» определяется только в пределах области видимости функции обратного вызова.

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

Я рекомендовал бы читать на «JavaScript переменной сферы»

1

Расширения на то, что Джош сказал, вы обзорные проблемы с «выходом» переменным. Вы можете исправить это, объявляя выход в верхней части вашей функции, как так: метод

var output; 
+0

Я не думаю, что проблема - проблема, и объявление 'output' наверху не поможет. Проблема заключается в асинхронном характере '$ .post'. – meagar

+0

OP упомянул, что они сделали синхронный вызов, установив async: false. –

-1

.post JQuery (в) по умолчанию для запуска асинхронно, то есть: пост() функция не останавливаться и ждать ответа , он сразу возвращается, а остальная часть вашего скрипта продолжается. В этом случае он переходит к вашему заявлению return.

И теперь мы доходим до классического состояния гонки ... может ли запрос AJAX завершить И выполнить function (data) до того, как остальная часть скрипта продолжается до обратного вызова? Учитывая, что большинство сетей имеют задержки, измеренные в миллисекундах, а обратный вызов будет выполняться через несколько микросекунд позже, скорее всего, не ... обратный вызов победит в гонке каждый раз.

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

простой способ сделать это, чтобы сделать две части функции а:

function do_ajax(parameters, data) { 
    if (data == null) { 
     jquery.post(
      .... 
      success: function(data) { do_ajax(parameters, data); } 
     ); 
    } else { 
     ... handle response here ... 
    } 
} 

Таким образом, функция может быть вызвана с тем, что данные, которые вы должны передать в вызов AJAX (parameters), и параметр data изначально равен нулю. Функция видит, что данные являются нулевыми, и делает материал AJAX. Как только ответ от сервера возвращается, функция снова вызывает себя, но это с предоставленными данными ответа, и вызывается другая часть функции, которая обрабатывает данные.

+0

Рад, что мне не нужно поддерживать код. Это самый смешной способ сделать это, о котором я мог подумать. Зачем вам снова называть do_ajax вместо функции, которая обрабатывает ответ? –

+0

@ Keith Я предполагаю, что это показалось ему более компактным? Но да, это действительно крутой способ сделать что-то. Объединение двух функций в одно, перегруженное через огромную if/else, является довольно грязной идеей, не говоря уже о ее рекурсивном вызове. – meagar

+0

@Keith. В чем разница между вызывающим аяксом, вызывающим себя, или вызовом другой функции? В любом случае, он должен вызвать функцию для обработки данных. По крайней мере, так, логика запроса и обработки хранится вместе. С некоторыми подходящими функциями-оболочками, чтобы вы не засоряли код с повторяющимися определениями URL-адресов, и что-то еще, я считаю, что это намного проще поддерживать, чем засорять мой код функциями «getX» и «handleX». –

0

Я бы не ожидал, что проблема будет связана с проблемами, поскольку JavaScript имеет область действия, а не область блока. Переменные, объявленные в любом месте функции, доступны в любом месте в функции.Вот почему JSLint мешает вам объявить их наверху: не потому, что это функционально важно, а потому, что это напомнит вам, что ваши переменные доступны , как будто они были объявлены наверху независимо от того, где вы их фактически объявляете. Попробуйте этот простой пример:

function ajax(callback) { callback(); } 
$(function() { 
    ajax(function() { x = 7; }); 
    alert(x); // x == 7 
}); 

Вопрос ваш $.post вызов является асинхронным. Вы доходите до линии return output; перед линией output = data;. Это происходит из-за того, что $.post немедленно возвращается и позволяет продолжить выполнение программы, в то время как происходит потенциально медленный вызов AJAX. Когда вызов AJAX завершается, он запускает обратный вызов complete.

Вам необходимо перестроить свой код, чтобы вы делали что-то с вашим значением внутри функции обратного вызова, которую вы передаете до $.post. Вы можете сделать это, передав в качестве параметра обратного вызова в get_rsrce_name():

function get_rsrce_name(onComplete) { 
    $.post(url, data, function(data) { onComplete(data); }); 
}