
31.05.2013, 23:41
|
Аспирант
|
|
Регистрация: 02.01.2011
Сообщений: 56
|
|
Не понимаю JavaScript. Как сделать ожидание события загрузки данных?
Есть у меня "класс", у которого сделан метод init(). В нем происходит вызов метода load() для загрузки данных с сервера (реализация jQuery 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? Как сделать чтоб отслеживалось?
|
|

01.06.2013, 01:23
|
 |
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,595
|
|
Сообщение от xintrea
|
Есть у меня "класс", у которого сделан метод init(). В нем происходит вызов метода load() для загрузки данных с сервера (реализация jQuery xmlrpc).
Задача: вызвать загрузку данных и дождаться результата. Если загрузка удачна - продолжить инит, если была ошибка - завершить инит.
|
Решение - добавить в init дополнительные функции, первая содержит порядок инициализации при успешной загрузке, вторая при неуспешной и вызывать их колбэком на событие загрузки.
Сообщение от xintrea
|
Проблема в строке с циклом while(). На нем скрипт затыкается как на бесконечном цикле.
...
Вопрос. Почему не работает этот кусок кода? Почему в цикле while() не отслеживаетс изменение свойства loadStatus?
|
Так и должно быть. Цикл javascript не делим, пока он не отработает никакие внешние события ни на что повлиять не смогут.(именно по этому предложенный выше вариант работать не будет также как и ваш)
Сообщение от xintrea
|
Как сделать чтоб отслеживалось?
|
Никак. В javascript невозможна "приостановка" выполнения вручную, т.к. код выполняется в одном потоке и эта самая приостановка вызвала бы полное прекращение взаимодействия со страницей как таковой.(что вы и наблюдаете при вечном цикле). Событийная модель является единственным нормальным вариантом, позволяющим пользователю продолжать работу со страницей пока идут какие-либо фоновые процессы.
Сообщение от xintrea
|
Флаги не помогают. Встраивать обработчики прямо в "линейный" код как лямбды - это издевательство, код получает рваный и плохо сопровождаемый.
|
Если делать всё как вы привыкли в другом языке - возможно. Однако всё выходит красиво и аккуратно если не тянуть чуждую идеологию из других языков, а писать изначально на javascript.
P.S. Если вы ооочень этого хотите и вам глубоко покласть на идеологию javascript, то можно использовать синхронный ajax запрос(именно то что вам нужно - с ожиданием загрузки и полной остановкой работы). Но это делать крайне не рекомендуется. Пример.
__________________
29375, 35
Последний раз редактировалось Aetae, 01.06.2013 в 02:36.
|
|

01.06.2013, 08:30
|
Аспирант
|
|
Регистрация: 02.01.2011
Сообщений: 56
|
|
> Сохраню кому нибудь рассудок, оставлю это здесь
Вы уверены, что этот код рабочий?
У вас же по сути генерируется куча xmlrpc запросов в цикле, пока самый первый запрос не отработает.
|
|

01.06.2013, 08:39
|
 |
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,595
|
|
Сообщение от xintrea
|
Вы уверены, что этот код рабочий?
|
Код нерабочий. Но не по этому:
Сообщение от xintrea
|
У вас же по сути генерируется куча xmlrpc запросов в цикле, пока самый первый запрос не отработает.
|
т.к. это неправда:
Сообщение от справочник
|
for ([initial-expression]; [condition]; [final-expression])
statement
|
initial-expression обрабатывается один раз перед началом цикла.
А почему нерабочий - читайте мой пост.
__________________
29375, 35
Последний раз редактировалось Aetae, 01.06.2013 в 08:45.
|
|

01.06.2013, 09:39
|
Аспирант
|
|
Регистрация: 02.01.2011
Сообщений: 56
|
|
Да, не доглядел что там for(), а мне уже везде while() мерещится.
Я впринципе понял, что интерпретатор javascript однопоточный, а реакция на отложенные события сделана через событийную модель. Поэтому блокировать поток ожиданием нельзя, так как обработчики событий обрабатываются между циклами main loop.
В свете этого мне посоветовали пользоваться коллбаками. И инит разбивать на цепочку функций:
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()
{
// Тут инит наконец-то завершен
...
}
Но проблема в том, что инит этого объекта не единственный. Существует ведь и вышестоящий код, который вызывает инит этого объекта. И он тоже должен дождаться пока инит этого объекта пройдет. И только когда инит этого объекта завершен, вызвать инит следующих объектов.
Получается, что в вышестоящем коде тоже надо делать цепочку вызовов с коллбаками.
А если есть еще выстоящий код (у меня четыре слоя) то и у них у всех тоже придется переделывать на цепочку функций с коллбаковыми вызовами? Я же с ума сойду.
|
|

01.06.2013, 11:28
|
 |
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,595
|
|
Сообщение от xintrea
|
А если есть еще выстоящий код (у меня четыре слоя) то и у них у всех тоже придется переделывать на цепочку функций с коллбаковыми вызовами? Я же с ума сойду.
|
Да да, всё переписать нафиг.  С самого начала надо было писать по-другому, но чего уж теперь. Если бы вы дочитали тот мой пост до конца, то обнаружили бы в самом низу работающий пример, показывающий как можно в данном конкретном случае получить желаемый вами результат.
__________________
29375, 35
|
|

01.06.2013, 13:40
|
Аспирант
|
|
Регистрация: 02.01.2011
Сообщений: 56
|
|
Нашел я вашу зарытую собаку, спасибо.
Вопрос: чем чревато использование async: false с вашей точки зрения?
|
|

01.06.2013, 17:18
|
 |
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,595
|
|
Сообщение от xintrea
|
Вопрос: чем чревато использование async: false с вашей точки зрения?
|
В первую очередь, временем ответа сервера случись чего. Если запрос один - таймаут соединения ещё спасёт, а если много то так и будет смотреть юзер на висящую страницу.)
__________________
29375, 35
|
|
|
|