Застывание страницы до полной загрузки php

Arantir

Новичок
Не знал, как более правильно это описать в названии темы, и в поиске не нашел...
В общем, вполне логично, что странница считается загруженной после выполнения всего php-кода. Но дело вот в чем: на странице есть пара функций, которые проверяют открытость порта на неких серверах. Это надо для того, чтобы отобразить, включены ли эти серверы.
Проверяю функцией fsockopen(). Последний параметр в ней - таймаут. Так вот, чтобы при большой нагрузке на сервер был виден истинный статус сервера, а не "оффлан" из-за отсутствия ответа от и так нагруженного сервера, то приходится ставить таймаут на несколько секунд, например 3.
Из-за того, что таких проверок несколько, это сильно оттягивает момент загрузки страницы.
Каждый переход по страницах занимает куда больше времени, чем надо.

Пробовал сделать показ статусов с помощью XMLHttpRequest() из javascripts. Ну то есть загрузки блока статусов уже после полной загрузки страницы. Но это не спасло, страница быстро загружалась, но просто начала застывать на те же несколько секунд после догрузки блока javascript'ом.

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

Натолкните на мысль, как это можно сделать...
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
В общем, вполне логично, что странница считается загруженной после выполнения всего php-кода.
Не логично. Страница считается сгенерированной на стороне сервера, а вот грузится к тебе она уже после.

Твое решение - проверять статусы кроном, записывая каждые минут 5 статус куда-то в файл, память или какой-то кеш, оттуда уже дергать без таймаута и показывать на странице. Если у тебя будет просроченная на 3 минуты инфа, никто не умрет. А вот на каждый пук-перезагрузку страницы юзать fsockopen - верный путь к бану на том сервере, если там админы следят за этим.
 

Arantir

Новичок
Не логично. Страница считается сгенерированной на стороне сервера, а вот грузится к тебе она уже после.
Так в том то и дело, что до выполнения fsockopen страница еще не сгерированная. Там идет "if fsockopen echo <html-код>", пока сокет не проверит, страницу не выдаст. Я не говорю, что задержка со стороны клиента, задержка-то на сервере. Но это ничего не меняет.
Хотя не могу понять, почему замирает вся страница, если блок с fsockopen подгружается через XMLHttpRequest()...
Твое решение - проверять статусы кроном, записывая каждые минут 5 статус куда-то в файл, память или какой-то кеш, оттуда уже дергать без таймаута и показывать на странице. Если у тебя будет просроченная на 3 минуты инфа, никто не умрет..
Не, 5 минут слишком долго... Ну с 1 минутой я бы еще смирился, а лучше - каждые 5 секунд... Это все равно менее затратно, чем на каждого пользователя. Но на хостинге сайта в кроне минимум 2 минуты.
А вот на каждый пук-перезагрузку страницы юзать fsockopen - верный путь к бану на том сервере, если там админы следят за этим.
А это мои сервера =) Они предназначены для нагрузок побольше, чем пара сотен проверок порта. Кроме того, будет видно, что запрос с IP сайта идет.

Это конечно идеальный вариант - обновлять одной процедурой, и показывать всем результат из файла. Но не очень актуальная информация получится.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Слишком долго? Ты для аэрокосмической области пишешь приложения что ли? Или это зуд "сделать все в стиле Паши Дурова, сразу, по-взрослому", хотя на самом деле нафиг не нужно.

Можешь хоть поставить на свой проверяемый сервер nginx, и отдавать оттуда картинку, гифку, с статусом.
 

Arantir

Новичок
А, хрен с ним. Поставил в крон и сделал подсказку, мол обновляется раз в 2 минуты. Знание этого должно размягчить ситуацию.
Все таки вы правы, что это не настолько критично, как могло бы быть в иной ситуации.

А вы в javascript хорошо разбираетесь? Мне до сих пор интересно, как бы подгрузить нечто, чтобы не тормозило всю страницу. Почему-то получение контента в XMLHttpRequest(), до полной загрузки первого, заставляет страницу застыть, даже курсор останется в виде руки, если на кнопке был. Просто при контенте в пару строк HTML-кода это не заметно, а вот при проверке сокета сразу видно...
Пробовал выполнять функцию в отдельном фрейме, а статус менять у самого окна-родителя. Все работает, но точно так же страница замирает.
Нет ли какого-то способа параллельно вот это дело подгружать? Ведь тут дело было даже не в загрузке какого-то количества информации, а в простой задержке до выполнения функции, причем со стороны сервера.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Arantir
JS в таких случаях, помнится, советовали запихивать вниз страницы. Ну а так, навскидку без кода не подскажу.
 

Gas

может по одной?
Arantir
насчёт ajax'а правильный ход мыслей, застывать страница не нужна, если ты явно не указал что запрос должен быть синхронным.
возьми какой-то js фреймворк, тот-же jquery (тыц) и его используй, а не напрямую XMLHttpRequest
 

Arantir

Новичок
Arantir http://ru.wikipedia.org/wiki/Сетевая_модель_OSI
ты разберись сначала, на каком уровне проверять "доступность" - на уровне сети (fsockopen) или на уровне приложения (XMLHttpRequest)
Что значит "на уровне приложения"? Скрипт загружает php-страницу, а в ней идет проверка fsockopen. Все что в данном случае делает приложение - выдает результат работы php в виде некого html-кода (например, слова "онлайн"). Если опустить лишний текст, то XMLHttpRequest выдает на страницу результат из fsockopen.
Arantir
насчёт ajax'а правильный ход мыслей, застывать страница не нужна, если ты явно не указал что запрос должен быть синхронным.
возьми какой-то js фреймворк, тот-же jquery (тыц) и его используй, а не напрямую XMLHttpRequest
Хм..Ничего лишнего вроде бы не указывал. Все делается примерно так:
PHP:
var content = XMLHttpRequest()
content.open("GET", <ссылка>, false);
content.send(null);
if (content.readyState == 4) {
<блок статуса>.innerHTML = content.responseText;
 

sobachnik

Новичок
Arantir
То, что ты описываешь, действительно похоже на то, что ты запрашиваешь данные "синхронно", а не "асинхронно". При использовании XMLHttpRequest-объекта - это третий параметр метода open, который может принимать значения true или false. True означает, что запрос будет "асинхронным" (при таких запросах страница не должна застывать в ожидании ответа от удалённого сервера), false - что запрос будет "синхронным" (страница замрёт в ожидании ответа).

возьми какой-то js фреймворк, тот-же jquery (тыц) и его используй, а не напрямую XMLHttpRequest
А разве jQuery не использует всё тот же XMLHttpRequest?
 

Arantir

Новичок
sobachnik
А вот где собака зарыта! Действительно false там указано. Надо было подробнее читать про эту функцию. Я в javascript не спец. =)
Спасибо за ответ!
 

Arantir

Новичок
sobachnik
Ой, плохо вышло, плохо... Страница теперь загружается сразу, но статусы так и не обновляются. Ни через прежние пару секунд, ни за следующие 5 минут...
Хотя ошибок, вроде, нет. alert() после content.open еще выполнился, значится open() выполилась корректно.
 

sobachnik

Новичок
Код:
var content = false;
if(window.XMLHttpRequest)
	content = new XMLHttpRequest();
else if(window.ActiveXObject)
	content = new ActiveXObject('Microsoft.XMLHTTP');
if(content) {
	dateObj = new Date();
	content.open('GET', 'ССЫЛКА?rnd=' + dateObj.getTime());
	content.onreadystatechange = function() {
		if(content.readyState == 4 && content.status == 200)
			БЛОК_СТАТУСА.innerHTML = content.responseText;
	}
	content.send(null);
}
 

sobachnik

Новичок
Раньше срабатывало у тебя именно из-за того, что был синхронный запрос. Т.е. выполнение JS кода также застывало до тех пор, пока не придёт ответ от удалённого сервера. После перехода на асинхронный запрос вот это вот:

if (content.readyState == 4) {
<блок статуса>.innerHTML = content.responseText;
Стало срабатывать сразу же после отправки запроса. Т.е. не дожидаясь ответа от сервера. И, естественно, условие не выполнялось, да и в блок статуса вставлять ещё нечего.
У XMLHttpRequest объекта свойство onreadystatechange предназначено специально для того, чтобы передавать в него функцию-обработчик (можно название функции просто передать, можно безымянную функцию), которая будет вызвана при изменении состояния запроса. В том числе при получении ответа от сервера.
 

Arantir

Новичок
sobachnik
Спасибо за подсказку с кодом =) Натолкнула на решение.
Убрал лишний false в одном месте и все получилось. Просто до этого это была функция догрузки страниц сайта без обновления всей страницы, там приходилось false на ссылку возвращать, на этом похоже и завтыкал.
Ну и onreadystatechange, конечно, помог окончательно.

Теперь все работает на 100% так, как мне хотелось!
 

Arantir

Новичок
А не подскажите еще, как заставить выполнятся js-функции в коде, выданном XMLHttpRequest? Просто есть страница с настройками сайта, там скрипт расставляет галочки в соответствии с включенными настройками (настройки в куках посетителя). Но при загрузке страницы через XMLHttpRequest() функции не выполняются, хотя явно вызваны. При идентичном коде в теле страницы все выполняется. Функция загрузки страниц в самом низу, перед </body>, так что DOM весь подгружен.
Я, вроде, даже пробовал их вызывать из функции, которая страницу подгружает, то есть вызов не лежит в подгруженном коде, и все равно ничего не вышло.
Хотя подгруженные функции с реакцией на нажатия кнопок и т.п. работают нормально. При этом и функции и кнопки были в подгруженном XMLHttpRequest'ом коде.
 

sobachnik

Новичок
Не сталкивался с таким раньше, никогда не пытался свойству innerHTML какого-либо объекта попытаться присвоить <script>...</script> с неким JS-кодом. Действительно, не работает. Ни в одном из браузеров, в которых проверял это. И дело не в том, что этот JS-код был получен через XMLHttpRequest, а даже если просто в самой страничке написать что-то типа

Код:
<html>
	<head>
		<title>test</title>
		<script type="text/javascript">
			function insertIt() {
				document.getElementById('i2').innerHTML = '<script type="text/javascript">document.getElementById(\'i1\').innerHTML = \'asdasd\';<\/script>';
			}
		</script>
	</head>
	<body>
		<a href="javascript:insertIt()">Insert it!</a>
		<div id="i1">i1</div>
		<div id="i2">i2</div>
		
	</body>
</html>
, то это не сработает...
Как вариант - отправляй JS-код не в теге <script>, а, например, в каком-нибудь div-е, а в функции, которая обрабатывает полученный ответ получай содержимое этого div-а и eval() его...
 

Arantir

Новичок
Самое интересное, что что-то вроде этого:
PHP:
<button id="but"></button>
<script>
document.getElementById('but').onclick = function () { alert('it works!'); }
</script>
не работает... НО! Вот это:
PHP:
<button id="but" onclick="a();">click</button>
<script>
function a() { alert('it works!'); }
</script>
уже прекрасно работает после прохождения через XMLHttpRequest... То есть можно с уверенность сказать, что браузер функции обработал и знает, что они существуют и даже знает, что по ним вызывается! Тем не менее прямые вызовы, даже просто alert(''), не работают.
 
Сверху