Это ШОК для чайника!
Недавно взялся разработать новую версию своего парсера лого в сервера SHOUTcast Прасер написан на PHP, при этом активно использует JavaScript (на простом уровне).
Я вообще в JavaScript новичок честно говоря. И меня это непонятное явление тронуло до глубины души, практически шокировав. :blink: Профессионалы, подскажите в чём прикол) Или в чём моя ошибка, если я туплю :) Чтобы не быть голословным, вот код селектора, написанного на JavaScript (это аналог переключателя страничек в любом поисковике, например в Яндексе, однако аналог скорее всего только лишь по внешнему виду и предназначению, реализовано-то в поисковиках это дело наверняка совсем по-другому :D ) PHP-код самого парсера приводить не буду, ибо огромный и сложный. Если потом понадобится, опубликую в отдельном посте. Итак, код нижнего фрейма: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" /> <title>Shoutcast log parser</title> <style type="text/css"> <!-- .style10 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: small;} a:link { color: #0000CC; } a:visited { color: #0000CC; } a.current { color: #EC7600; } --> </style> </head> <body> <script language="JavaScript" type="text/javascript"> function changePage(ref) { obj = document.frm obj.action = ref obj.submit.click() } function init() { } function check() { return (frm.filename.value != '') } function addData(str) { if (main_part == '') main_part = document.frm.innerHTML document.frm.innerHTML = str + main_part //document.getElementById('tracker').innerHTML = str } var main_part = '' function printPageList(pages, group, cur_page) { flag = true; var buf = '' var from = parent.topframe.getFrom() var to = parent.topframe.getTo() var grouping = document.getElementById('grouping').checked ? 'true' : 'false'; buf += '<table border="0"><tr>' if (cur_page == 10) { cur_page = 0 } if (group > 0) { buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=0\'); return false"><<</a> </td>' buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + ((group - 1) * 10) + '\'); return false"><</a> </td>' } for (i = group * 10 + 1; i <= (group + 1) * 10; i++) { if (i > pages) { break; } style = '' if (i % 10 == cur_page) { style = ' class="current"' } buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + (i-1) + '\'); return false"' + style + '>' + i + '</a> </td>' } if (pages>10) { if (i <= pages) { if ((group + 1) * 10 + 1 <= pages) { buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + ((group + 1) * 10) + '\'); return false">></a> </td>' } buf += '<td><a href="#" onclick="changePage(\'parser.php?total=' + pages + '&from=' + from + '&to=' + to + '&page=' + (pages - 1) + '\'); return false">>></a></td>' } buf += '<td> всего ' + pages + '</td>'; } buf += '</tr></table><br>' addData(buf) } </script> <!--<span id="tracker" class="style10"></span>--> <form action="parser.php" name="frm" id="frm" target="topframe" method="post" enctype="multipart/form-data" class="style10"> <p><input type="checkbox" name="grouping" id="grouping">Группировать смежные сеансы</p> <input type="file" name="filename" size="38"><br><br> <input type="submit" name="submit" value="Анализ"><br> </form> </body> </html> Собственно, дело вот в чём. Во второй версии скрипта при загрузке нового блока PHP-скрипт в верхнем фрейме с помощью JS по событию onload перенаправлял селектор в нижнем фрейме по новому URL, передавая в адресной строке новые параметры, которые использовались селектором для обновления раскладки. Но вот я решил что это не есть хорошо (например, у меня при этом значение поля с именем анализируемого файла очищалось, и почему-то через JS с помощью функции из родительского фрейма не восстанавливалось), и в третьей версии решил сделать механизм, который позволит обновить нужную часть нижнего фрейма без перезагрузки. Для этого я убрал из селектора парсинг URL и вместо этого добавил в функцию вывода раскладки три аргумента. Сперва я попробовал работать напрямую с document.frm.innerHTML, где frm - имя формы, но, как выяснилось, почему-то данные, добавленные посредством модификации innerHTML из сценария, не читаются, будто их и нет. Поэтому удалить старую раскладку таким способом не получалось. Полностью очистить innerHTML я не мог, потому что там содержался ряд других контролов и надписей. Недолго думая, я нашёл вариант, который уже применял когда-то в другой онлайн-системе с интернет-радио: завести глобальную переменную и хранить в ней исходное состояние innerHTML. Да, наверное это ужасно плохой стиль, но я ничего лучше не придумал. Оно заработало. Но тут я подумал: а почему мне надо обязательно пихать таблицу с номерами внутрь формы, ведь можно сделать ей отдельный контейнер! И очищать его перед обновлением. Сказано - сделано. Я сделал всё как описано выше, и тут начинается фантастика. В вышеописанном коде есть оба варианта решения - через глобальную переменную и через отдельный контейнер (второй сейчас закомментирован). Парадокс в том, что второй, более человеческий способ тормозит как не знаю что. Я специально проводил отсчёт времени переключения между страницами данных. В случае помещения трекера в отдельный див, между нажатием на ссылку и осуществлением загрузки верхнего скрипта, который после её завершения вызывал JS функцию селектора, я успевал досчитать до девяти (!). То есть около 9 секунд. В случае же хранения HTML разметки формы в глобальной переменной, при всей нелепости подхода, я едва успевал сосчитать до двух (1,5-2 секунды!) :blink: Я до сих пор слегка в ауте. PHP-код один и тот же, остальное не менялось, единственное существенное отличие которое я вижу - в первом случае использован метод document.getElementById() (при чём документ мягко говоря не очень большой, пара инпутов, форма, див и обчёлся), во втором же случае происходит обращение упрощённым способом к самой форме: document.frm Я конечно слышал, что ссылки на формы хранятся браузером как-то особо, для упрощённого вызова. Но getElementById() используется повсюду!.. Ну не верю я чтобы он у всех так тормозил. Он что, ТАК долго обходит дерево? :blink: Какие тогда возможны альтернативы? :( Или я где-то жёстко затупил... Прошу помочь разобраться! :) |
1. Много кода.
2. Много букв. 3. Цитата:
Это отбивает любое желание разобраться и помочь. Я не могу утверждать, что я понял всё из вышенаписанного, но раз там промелькнуло упоминание фрейма, возможно, задержка вызвана загрузкой документа, всех его элементов и построением соответствующего дерева. Если не нужно ждать загрузки элементов, а хватит только дерева, отлавливайте не onload, а domReady (google -> domready). Если нужен только код страницы, используйте XHR (страница при этом должна быть на том же домене). |
Я прошу прощения :)
Но я тоже ровно ничего не понял. :-? Давайте я переформулирую вопрос корректнее, а Вы уточните, что Вы имели в виду) ОК? "Селектор" - я немного некорректно употребил это слово. Пускай будет "трекер". Селектором я его назвал от слова "select" - он выбирает, какая часть файла будет анализировться, или, говоря на языке конечного пользователя, какую страничку обработанных данных покажет ему скрипт. Насчёт onload - опять же ни в чём не уверен, но не думаю что дело именно в этом. Ведь событие и в первом и во втором случае вешается на onload. Более того, я вообще не уверен что проблема в JS (хотя ручаюсь, что PHP код абсолютно идентичен в обоих случаях). Понимаете, просто такое ощущение, что "висит" именно PHP. Причём во всех браузерах. И только в случае отдельного контейнера. Ну как такое возможно? В принципе, есть у меня предположение... Только что сообразил. Возможно, проблема как раз-таки в том, что в случае с отдельным контейнером поле с файлом не очищается. Хоть я и сделал в PHP логику, чтобы при наличии загруженного файла на сервере и установленной куке в клиенте повторной загрузки не происходило, возможно, данные каким-то образом всё же утекают и передаются на сервер снова через форму. То есть такая огромная задержка вызвана тупо повторной загрузкой 5-мегабайтного файла. Но PHP судя по отладочной печати его не сохраняет. Может ли быть так, что данне передаются "вхолостую"? То есть послали, но не приняли?.. И если это так, то как с этим бороться? Каждый раз грузить весь огромный лог - Боже упаси, а очищать поле не хочется, т.к. для пользователя это единственный источник информации о том, какой лог он анализирует. Сделать отдельный "дисплей" с именем файла? Увы, у меня места на него нет, да и пустое поле загрузки смотрится не очень красиво... Можно ли как-то обойти эту проблему через JS? Например, запретить загрузку на сервер части формы? Можно конечно вообще форму не сабмитить, я не спорю, а только пренаправлять верхний фрейм с PHP-скриптом. Это так, но что делать, если юзер-таки захочет загрузить новый лог? Надо вообще разделить процесс загрузки файла с логом и процесс переключения страниц. Но как это сделать органично? Тут ведь в чём была прелесть - нажал "Анализ" - и тут же получил результат, так как скрипт в конце стадии подготовки сам устанавливал текущую страницу в ноль и шёл работать дальше. Для пользователя всё было совершенно прозрачно. Кроме того, в ближайшие 10 минут пользователь мог нажать "Анализ" вообще не выбирая файл. Скрипт сам соображал, что файл уже загружен и брал его с сервера. Если сейчас эти процессы разделять - может выйти неудобно с точки зрения юзабилити :( |
В итоге оставил первый вариант чтобы не мачиться)
|
Часовой пояс GMT +3, время: 18:33. |