Не понимаю JavaScript. Как сделать ожидание события загрузки данных?

xintrea

Новичок
Есть у меня "класс", у которого сделан метод init(). В нем происходит вызов метода load() для загрузки данных с сервера (по xmlrpc).

Задача: вызвать загрузку данных и дождаться результата. Если загрузка удачна - продолжить инит, если была ошибка - завершить инит.

Код:
// Глобальные переменные - статусы загрузки данных с сервера
var lb_load_status_ok=0;
var lb_load_status_in_process=1;
var lb_load_status_error=2;

...

function LBTeamData() 
{
 var loadStatus;

 this.init = function(id) 
 {
  // Загрузка с сервера информации
  this.load(id);
  
  // Ожидание завершения загрузки
  while( loadStatus==lb_load_status_in_process ){};

  // Если была ошибка  
  if(loadStatus==lb_load_status_error)
   return;
  
  // ... здесь продолжается инициализация ... 
 };
 

 this.load=function(teamId) 
 {
  loadStatus=lb_load_status_in_process;

  var that = this;

  // Получение данных о команде  
  $.xmlrpc({
        url: 'http://'+window.location.host+'/XmlRpcServer',
        methodName: 'getTeam',
        params: [teamId],
        success: function(response, status, jqXHR){ that.successLoad(response, status, jqXHR); },
        error: function(jqXHR, status, error) { that.errorLoad(jqXHR, status, error); }
  });

 };


 // Обработчик получения данных
 this.successLoad=function(response, status, jqXHR) 
 {
  loadStatus=lb_load_status_ok;

  name=response[0]['name']; // Название команды
  unitsNames=response[0]['unitsNames']; // Имена игроков

  alert("Success load data from server");
 };


 // Обработчик ошибки при получения данных
 this.errorLoad=function(jqXHR, status, error) 
 {
  loadStatus=lb_load_status_error;

  alert("Error at getting team data from server: "+error);
 };

}
Проблема в строке с циклом while(). На нем скрипт затыкается как на бесконечном цикле.

Если его убрать, то через некоторое время появится сообщение "Success load data from server". Это свидетельствует о том, что данные в подгружаются нормально.

Но я не могу понять, как в "линейном" коде метода init() дождаться появления этих данных. Флаги не помогают. Встраивать обработчики прямо в "линейный" код как лямбды - это издевательство, код получает рваный и плохо сопровождаемый.

Вопрос. Почему не работает этот кусок кода? Почему в цикле while() не отслеживаетс изменение свойства loadStatus? Как сделать чтоб отслеживалось?
 

WMix

герр M:)ller
Партнер клуба
так
PHP:
while( loadStatus==lb_load_status_in_process ){};
совершенно не правильно
у тебя есть на руках
PHP:
success: function(response, status, jqXHR){ that.successLoad(response, status, jqXHR); },
там загрузка произошла, от туда и пляши!
поломай свой мозг, думай callback'ами
 

xintrea

Новичок
поломай свой мозг, думай callback'ами
Я понял вас, но остался вот какой вопрос.

Предположим, переделал я LBTeamData.init() на цепочку вызовов:

Код:
this.init = function(id) 
 {
  // Загрузка с сервера информации
  this.load(id, this.init_second_callback() );
 }

this.init_second_callback = function() 
 {
  // Тут еще какие-то действия, еще какая-то подгрузка информации  
  this.loadFormula(id, this.init_third_callback() );
 }

this.init_third_callback = function() 
 {
  // Тут инит наконец-то завершен
  ...
 }
В load() и loadFormula(), точнее, в обработчиках событий получения данных, сделаны вызовы коллбаков. Все вроде понятно.

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

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

WMix

герр M:)ller
Партнер клуба
если действие может быть сделано ТОЛЬКО после возникновения некоторого события, вызов этого действия пишем напосредственно в callback функции возникновения этого события.
для тебя
И он тоже должен дождаться пока данный класс проинитится, перед тем как инитить следующие объекты.
значит вызов данного инита должен быть в методе появления события о завершении.

если чесно звучит кривовато. возможно ему не нужно ждать, а "инится" параллельно? почему он должен дождаться?
 

xintrea

Новичок
> значит вызов данного инита должен быть в методе появления события о завершении.

То есть, городить огород с каллбаками придется и в вышестоящем коде. Блин, я сойду с ума, у меня четыре таких слоя.


> возможно ему не нужно ждать, а "инится" параллельно? почему он должен дождаться?

Потому что от тех данных, которые проинитится в объекте LBTeamData зависит логика инита дальнейших объектов.
 

WMix

герр M:)ller
Партнер клуба
все проще, не нужно ждать события, можно описать действия после его возникновения. 4й 10й слой не важно. пишем что нужно делать если это случилось в переданной лямде.
Потому что от тех данных, которые проинитится в объекте LBTeamData зависит логика инита дальнейших объектов.
может это уже не инит? в моем понимании инит это создание независимого от логики каркаса.

возможно тебе поможет знание, что можно создавать свои события и привязывать к этим событиям обработчик.

к примеру происходят 2 различных по цепочке события ajax.success и onchange, каждое из которых создает новое одинаковое событие "обновились данные", к которому привязан обработчик. обновления числа в элементе DOM

http://perevodik.net/ru/posts/17/
 
Сверху