2014-09-26 1 views
0

У меня есть пара функций, которые используют вызов jQuery AJAX для извлечения XML-файла с моего сервера и преобразования его в нечто полезное. Посмотрите на следующий код:JavaScript/jQuery AJAX - получение моих асинхронных данных обратно в мою синхронную программу

getBalanceXML: function (callback) { 
    $.ajax({ 
     type: 'GET', 
     url: 'Content/saldotracking.xml', 
     dataType: 'xml', 
     success: callback, 
     error: function() { throw new Exception("getBalanceXML(): Failed to load XML file"); } 
    }) 
}, 

getBalanceBarChart: function (xml) { 
    var balanceArray = []; 
    $(xml).find('Balance').each(function() { 
     var nodeObject = { 
      //fill a JavaScript object with values from the XML file in the format I need 
      } 
     balanceArray.push(nodeObject); 

    }); 
    console.log(balanceArray); 
    return balanceArray; 
} 

Теперь, когда я называю эту функцию:

var stuff = getBalanceXML(getBalanceBarChart); 
alert(typeof(stuff)); 

материал вар еще не определено. Следуя другим ответам на StackOverflow, я передаю функцию getBalanceChart в качестве параметра функции getBalanceXML, которая выполняет вызов AJAX. Успех! Теперь getBalanceChart может также использовать XML-файл, полученный от вызова AJAX. Однако все, что я сделал, это переместить проблему синхронизации в другую функцию. Наступает момент, когда синхронной части моей программы нужен массив, который поступает из асинхронной функции.

Что мне делать?

+1

Читать эту тему: http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call – epascarello

+0

Вы не можете. Это совершенно невозможно. Если вы используете асинхронные данные, вся ваша программа становится асинхронной. – Bergi

ответ

1

отредактированы добавить код

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

var stuff = getBalanceXML(getBalanceBarChart); 

Если я правильно понимаю вашу потребность правильно , это должно сортировать вас:

  1. s туф глобально доступной переменной

  2. В вашем getBalanceBarChart не возвращают значение, а не назначать его вещи непосредственно

  3. (по желанию) можно затем, по-прежнему в функции getBalanceBarChart, инициировать некоторые другие действия, которые вы можете предпринять.

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

Надеюсь, что это поможет.

getBalanceBarChart: function (xml) { 
var balanceArray = []; 
$(xml).find('Balance').each(function() { 
    var nodeObject = { 
     //fill a JavaScript object with values from the XML file in the format I need 
     } 
    balanceArray.push(nodeObject); 

}); 
console.log(balanceArray); 

// DO not return value, instead assign it to a variable directly, 
// since this will only occur after any asynchronous processing 

myGlobalVariable = balanceArray; 

// optional : someOtherFunction(); 
} 
+0

Установка переменной вне функциональной цепочки вместо того, чтобы возвращать что-либо, отлично работает! Спасибо за вашу помощь. – ohyeah

0

То, что происходит в том, что вы присваиваете stuff значение, возвращаемое из getBalanceXML, что нет ничего, или undefined. Вызов AJAX не блокируется, поэтому getBalanceXML запускает AJAX и сразу же выходит из функции.

Я хотел бы сделать что-то вроде этого:

$.ajax({ 
    type: 'GET', 
    url: 'Content/saldotracking.xml', 
    dataType: 'xml'   
}).done(function(xml) { 
    var balanceArray = []; 
    $(xml).find('Balance').each(function() { 
     var nodeObject = { 
      //fill a JavaScript object with values from the XML file in the format I need 
     } 
     balanceArray.push(nodeObject); 
    }); 
    console.log(balanceArray); 

    // Do something with balanceArray 
    // ex. updateBalance(balanaceArray); 

}).fail(function() { 
    throw new Exception("getBalanceXML(): Failed to load XML file"); 
}); 
+0

Это решение работает для меня (я пробовал), но это оставляет вам гигантскую функцию, которая выполняет множество разных вещей, что затрудняет тестирование и поддержку. – ohyeah

+0

Я уверен, что он может использовать немного рефакторинга, но я не понимаю, как это было бы менее проверено, чем то, что у вас было до этого. Если ваши потребности более сложны, и вам нужна привязка данных или что-то в этом роде, то Backbone/Angular/Ember проделали бы долгий путь для повышения ремонтопригодности вашего кода. Но если это будет просто, то это наверняка будет излишне. – derekmckinnon

Смежные вопросы