webhamster
@webhamster

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

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



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



Вот код:



// Глобальные переменные - статусы загрузки данных с сервера<br>
var lb_load_status_ok=0;<br>
var lb_load_status_in_process=1;<br>
var lb_load_status_error=2;<br>
<br>
...<br>
<br>
function LBTeamData() <br>
{<br>
 var loadStatus;<br>
<br>
 this.init = function(id) <br>
 {<br>
  // Загрузка с сервера информации<br>
  this.load(id);<br>
  <br>
  // Ожидание завершения загрузки<br>
  while( loadStatus==lb_load_status_in_process ){};<br>
<br>
  // Если была ошибка  <br>
  if(loadStatus==lb_load_status_error)<br>
   return;<br>
  <br>
  // ... здесь продолжается инициализация ... <br>
 };<br>
 <br>
<br>
 this.load=function(teamId) <br>
 {<br>
  loadStatus=lb_load_status_in_process;<br>
<br>
  var that = this;<br>
<br>
  // Получение данных о команде  <br>
  $.xmlrpc({<br>
        url: 'http://'+window.location.host+'/XmlRpcServer',<br>
        methodName: 'getTeam',<br>
        params: [teamId],<br>
        success: function(response, status, jqXHR){ that.successLoad(response, status, jqXHR); },<br>
        error: function(jqXHR, status, error) { that.errorLoad(jqXHR, status, error); }<br>
  });<br>
<br>
 };<br>
<br>
 // Обработчик получения данных<br>
 this.successLoad=function(response, status, jqXHR) <br>
 {<br>
  loadStatus=lb_load_status_ok;<br>
<br>
  name=response[0]['name']; // Название команды<br>
  unitsNames=response[0]['unitsNames']; // Имена игроков<br>
<br>
  alert("Success load data from server");<br>
 };<br>
<br>
 // Обработчик ошибки при получения данных<br>
 this.errorLoad=function(jqXHR, status, error) <br>
 {<br>
  loadStatus=lb_load_status_error;<br>
<br>
  alert("Error at getting team data from server: "+error);<br>
 };<br>
<br>
}<br>




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



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



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



Вопрос. Почему не работает этот кусок кода? Почему в цикле while() не отслеживаетс изменение свойства loadStatus? Как сделать чтоб отслеживалось?
  • Вопрос задан
  • 12467 просмотров
Пригласить эксперта
Ответы на вопрос 5
jdponomarev
@jdponomarev
Конечно зависает, это же и есть бесконечный цикл.
Передайте, например, в функцию load колбек

this.load=function(teamId,callback) {

};

и вызывайте его после загрузки
success: function(response, status, jqXHR){ that.successLoad(response, status, jqXHR); callback(); }

а в init — this.load(id,function(){
alert(«я загрузился»);
});
Ответ написан
@Fantyk
web developer
Посмотрите в сторону объекта Deferred, пример с ajax:

function LBTeamData(id){

    this.init = function(id) {
        // Загрузка с сервера информации
        this.load(id).done(function() {
           // ... здесь продолжается инициализация ... 
          alert("продолжаем после успешного запроса");
        }).fail(function(message) {
          alert('ошибка..')
        });
    };
     
    this.load=function(teamId){
        var dfr = $.Deferred();
        alert('посылаем запрос');
        $.ajax({
                url: '2.php',
                success: function(response, status, jqXHR){ dfr.resolve();},
                error: function(jqXHR, status, error) { dfr.reject() ; }
        });
        return dfr;
    };

    this.init();

};


Также существует ряд библиотек-оберток для этого объекта, мне в свое время приглянулась JSDeferred
Ответ написан
@kxyu
Но я не могу понять, как в «линейном» коде метода init() дождаться появления этих данных.

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

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


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

Встраивать обработчики прямо в «линейный» код как лямбды — это издевательство, код получает рваный и плохо сопровождаемый.


Это javascript, привыкайте
Ответ написан
Комментировать
fear86
@fear86
Developer
Просто надо заменить асинхронный вызов, на синхронный.
Ответ написан
@andrevinsky
Возможно, это поможет? habrahabr.ru/post/210820
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы