Jan
16
|
jQuery, $.getJson, $.ajax и все, все, все…
|
До этого я работал только с Prototype, особо jQuery не пользовался, хотя и использовал пару вполне успешно.
В проекте, в котором я сейчас работаю, все построено на Zend Framework + JQuery. Соответственно приходиться сталкиваться теперь довольно часто с jQuery.
Вчера мне понадобилась там одна фишка: нужно было получить данные через Ajax запрос и дальше сделать с ними некоторые манипуляции (обрезание строки и т.д, не суть важно) и вывести клиенту.
Недолго думая, была сделана такая конструкция:
$.getJSON(’<?=$this->newsLetterUrl(’content-start’)?>/’,
{ load_eds_data: 1, idpage: $(’#eds_ref-key’).val(), ajax: ’true’},
function(data) {
subTitle = ’Dates: ’+data.date_text + ’ Venue: ’ + data.xvenue;
});
Удивление наступило позже, когда я понял, что переменная subTitle не видна после этого и не доступна.
Полез в гугл, начал искать, что ж это за фигня получается, что нельзя в переменную записать данные после ajax запроса.
Оказалось, что проблема … в асинхронности запроса $.getJson и для того, чтобы получить нужное мне, конструкцию надо заменить на такую:
$.ajax({
async: false,
data: { load_eds_data: 1, idpage: $(’#eds_ref-key’).val(), ajax: ’true’},
dataType : «json»,
url: ’newsLetterUrl(’content-start’)?>/’,
success: function(data) {
subTitle = ’Dates: ’+data.date_text + ’ Venue: ’ + data.xvenue;
}
});
указав таким образом, что нам нужен неасинхронный запрос. Теперь переменная subTitle видна поза данной конструкцией! И ее можно использовать дальше, как угодно.
Самое интересное, что в prototype таких проблем у меня вообще не возникало. Видимо связано с особенностями реализации библиотеки.
Возможно кому-то пригодится, когда столкнетесь с подобной задачей.
16.01.2010 в 17:32
Как это она во втором случае видна!?!?!?!?!? О_О
Да вы что.. локальная переменная функции видна за её пределами!?!?!?!?! Советую срочно писать багрепорт разработчикам… ибо если работает действительно как у вас, то если у меня есть переменная subTitle в коде – то после вызова вашего аякс-запроса её значение будет перезаписано!!!! что в общем-то мягко-говоря очень хреново!!!
16.01.2010 в 17:39
Steward:
Советую сначала ознакомиться с принципами области видимости в javascript.
Вот простой пример:
a будет равно 3.
Удивлены? А я нет. Читайте больше тут – http://freeprogs.kiev.ua/2007/09/ob-oblastyah-vidimosti-v-yazikah-programmirovaniya/
16.01.2010 в 17:46
Чему тут позвольте удивляться? Тому, что вы объявили глобальное определение переменной и присвоили ей значение в функции? Вы издеваетесь – скажите честно?
пы.сы.
и поправьте свой комментарий… не очень приятно когда алерт выскакивает на странице
16.01.2010 в 18:06
Steward:
Нет, я пытаюсь показать, что вы ошибаетесь. Все работает как и должно.
Усложняем задачу:
Поправил
16.01.2010 в 18:18
Да.. моя опять перепутать )) вечно эта видимость в JavaScript ставит меня в тупик… это если в функции перед переменной написать var – она будет локальной… – с этим разобрались ))
А вот с исходным сообщением непонятно.. в документации чётко написано что callback вызывается когда запрос успешно завершён… __успешно__ и __завершён__ – следовательно синхронный он БЫЛ или нет уже в общем-то пофиг…
Действительно странная фича (о которой тоже неплохо было бы сообщить разработчикам)
16.01.2010 в 18:29
Steward:
Снова вы ошибаетесь.
Это все так, но проблема в том, что $.getJson асинхронен по сути и его выполнение может завершаться позже, чем загрузка всей страницы, он не зависит от загрузки страницы. Поэтому результат не доступен во время загрузки остальной части страницы.
Все происходит вот так:
Идет загрузка страницы, доходит до вызова $.getJson, он начинает выполняться, а страница не дожидаясь возврата ее результата – продолжает грузиться дальше, не зная о данных, что вернулись ровно ничего.
К разработчикам тут снова нет смысла писать, все сделано как и должно быть. Тоесть callback вызывается и вы правильно написали, когда запрос выполнен и успешен, но страница не ожидает пока запрос что-то вернет
16.01.2010 в 18:38
Ну вы меня окончательно запутали – я то думал это запрос выполняется для уже загруженной страницы (onClick какой-то кнопки), а оказывается этот скрипт выполняется в процессе загрузки основной страницы и вы ещё аяксом пытаетесь что-то где-то получить (зачем так делать это другой вопрос) .
Можно было-бы коротко и ясно написать: запрос $.getJSON всегда асинхронный – и всё )) – всё было бы понятно. Естественно что для дальнейшей работы скрипта (текст которого ещё возможно только загружается) необходима доступность и готовность всех предыдущих объявленных данных.
Только я дурак и всё не понял с самого начала? (это вопрос не к автору )
16.01.2010 в 18:43
Я не проверял, но думаю, что если бы это было для onclick, результат был бы такой же.
Просто интерпретатор не ожидает возврата результата и выполняет дальнейший кусок кода, запустив асинхронный запрос к серверу.
16.01.2010 в 18:46
Кстати из официального мануала по этому методу:
http://docs.jquery.com/Ajax/jQuery.getJSON
Это означает, что он всегда асинхронный.
16.01.2010 в 18:53
Ну по логике.. callback функции как раз и нужны чтобы определить что запрос выполнился полностью.
А по поводу строчки из мануала – она меня слегка озадачила – нельзя что ли было написать “asynchronous request”?
17.01.2010 в 14:46
Глобальные переменные – это зло, и тем не менее, их продолжают использовать
По моему правильнее было бы сделать:
- оставить запрос асинхронным;
- на beforeSend повесить “loading…”
- на success повесить callback типа:
function(data) {
subTitle = ’Dates: ’+data.date_text + ’ Venue: ’ + data.xvenue;
prepareData(subTitle); /* дальше сделать с ними некоторые манипуляции (обрезание строки и т.д, не суть важно)*/
showData(); /*и вывести клиенту.*/
hideLoading();
}
17.01.2010 в 14:47
да и лучше
var subTitle = ...
18.01.2010 в 03:31
@naspeh
гасить анимацию лучше в ‘complete’, а не через hideLoading(); потому как запрос вполне себе может закончиться неудачей.
18.01.2010 в 08:57
вопрос не в этом , но с лоадингом да, лучше в ‘complete’
15.02.2010 в 00:15
naspeh, рад тебя видеть в своем блоге. Давно от тебя ничего не слышал вообще.
Кстати, кусок кода, который обсуждался в данной заметке – в итоге пришлось вообще выкинуть, т.к. появились новые требования у заказчика проекта, поэтому эту довольно странную конструкцию просто удалил.
15.02.2010 в 01:14
твой блог у меня еще в reader-е так что иногда читаю, а комменты обычно вообще нигде не оставляю, а тут, честно, задело душу программиста, ИМХО нельзя рекомендовать неправильные подходы, поэтому ответил…