Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Общие вопросы > AJAX и readyState=3 (проблема в IE)


Автор: InvalidProperty 1.11.2007, 11:33
уже 5 часов лажу по форумам, ничего конкретного найти не могу, за исключением 
http://forum.vingrad.ru/forum/topic-150096/unread-1/hl/ajax/index.html, но и это, к сожалению, не подошло, а, может быть, я сам что-то неправильно делаю.

Для начала предоставлю исходный код JS:

Код

var xmlHttp;
var is_IE;

function getXmlHttpObject()
{
// Firefox, Opera 8.0+, Safari
 try
  { xmlHttp = new XMLHttpRequest(); is_IE = false; }
 catch (e)
 {
// Internet Explorer
  try
   { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); is_IE = true; }
  catch (e)
  {
   try
    { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); is_IE = true; }
   catch (e)
    { return null; }
  }
 }

 return xmlHttp;
}

function getIndexReadyState()
{
  document.getElementById('errors').innerHTML = "<div class=\"headholder info_headholder\">-1. -= processing =-</div>\n" +
     "<div class=\"placeholder info_placeholder\">\n" +
     window.xmlHttp.responseText + "\n</div>";
}

function showIndexReadyState()
{
 window.xmlHttp = getXmlHttpObject();
 if(window.xmlHttp == null)
 {
  alert("Your browser does not support AJAX!");
  return false;
 }

 window.xmlHttp.open("GET", "index_ajax.php?r=" + Math.random(), true);

 if(window.is_IE)
  window.xmlHttp.send();
 else
  window.xmlHttp.send(null);

 window.setInterval(getIndexReadyState, 1000);

 return true;
}


Серверный код может быть абсолютно любым, например, на PHP:

Код

echo "state 1 ";
flush();
sleep(5);
echo "state 2 ";
flush();
sleep(5);
echo "state 3";


Таким образом, на выходе мы должны получить
state 1
через 5 секунд
state 1 state 2
еще через 5 секунд
state 1 state 2 state 3

Mozilla firefox и konqueror выдают именно то, что нужно, а вот IE говорит (цитирую)

данные, необходимые для завершения этой операции, еще недоступны smile 

Я уже запарился искать в чем может быть проблема, хотя, скорее всего, она в кеширование IE, но что делать?
Я пробовал изменить JS функцию getIndexReadyState() следующим образом:

Код

function getIndexReadyState()
{
 if(typeof(window.xmlHttp.responseText) == "string")
 {
  document.getElementById('errors').innerHTML = "<div class=\"headholder info_headholder\">-1. -= processing =-</div>\n" +
     "<div class=\"placeholder info_placeholder\">\n" +
     window.xmlHttp.responseText + "\n</div>";
 }
}


FFx и konqueror также делают все так, как нужно, т.е. каждые 5 секунд вываливают обновленные данные, а вот IE в этом случае ошибки не выдает, но вываливает данные, только когда readyState = 4, т.е. в самом конце отдает целиком всю строку
state 1 state 2 state 3

В чем может заключаться проблема?

Автор: InvalidProperty 1.11.2007, 17:03
немного разобрался с работой AJAX, хотя и не так, как хотелось. Вот рабочий код Javascript

Код

var is_IE;
var xmlHttp;
var xmlHttp_read;

function getXmlHttpObject()
{
// Firefox, Opera 8.0+, Safari
 try
  { xmlHttp = new XMLHttpRequest(); is_IE = false; }
 catch (e)
 {
// Internet Explorer
  try
   { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); is_IE = true; }
  catch (e)
  {
   try
    { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); is_IE = true; }
   catch (e)
    { return null; }
  }
 }

 return xmlHttp;
}

function getIndexReadyState()
{
 if (xmlHttp_read.readyState == 4) 
 {
  if (xmlHttp_read.status == 200) 
  {
   try
   {
    if(xmlHttp_read.responseText == "R_OK")
    {
     xmlHttp = null;
     xmlHttp_read = null;
     return;
    }

    document.getElementById('errors').innerHTML = "<div class=\"headholder info_headholder\">-1. -= processing =-</div>\n" +
     "<div class=\"placeholder info_placeholder\">\n" +
     xmlHttp_read.responseText + "\n</div>";

    setTimeout("getData();", 500);
   }
   catch(e)
    { alert("Error reading the response: " + e.toString()); }
  }
  else
   alert("There was a problem retrieving the data:\n" + xmlHttp_read.statusText);
 }
}

function getData()
{
 xmlHttp_read.open("GET", "index_ajax.php", true);
 xmlHttp_read.onreadystatechange = getIndexReadyState;
 if(is_IE)
  xmlHttp_read.send();
 else
  xmlHttp_read.send(null);
}

// <for index.php>
function showIndexReadyState()
{
 xmlHttp = getXmlHttpObject();
 xmlHttp_read = getXmlHttpObject();
 if(xmlHttp == null || xmlHttp_read == null)
 {
  alert("Your browser does not support AJAX!");
  return false;
 }

 xmlHttp.open("GET", "index_ajax.php?start=1", true);

 if(is_IE)
  xmlHttp.send();
 else
  xmlHttp.send(null);

 setTimeout("getData();", 500);

 return true;
}
// </for index.php>


а вот это крутится на стороне сервера:

Код

<?php
if($_GET["start"] === "1")
{
    $fd = fopen("tmp/1.res", "w");
    fwrite($fd, "state 1 - prepare");
    fclose($fd);
    sleep(5);
    $fd = fopen("tmp/1.res", "w");
    fwrite($fd, "state 2 - generate");
    fclose($fd);
    sleep(5);
    $fd = fopen("tmp/1.res", "w");
    fwrite($fd, "state 3 - done");
    fclose($fd);
    sleep(5);
    $fd = fopen("tmp/1.res", "w");
    fwrite($fd, "R_OK");
    fclose($fd);
}
else
{
    if(($fd = @fopen("tmp/1.res", "r")) === FALSE)
     die();
    $s = fread($fd, filesize("tmp/1.res"));
    fclose($fd);
    if($s == "R_OK")
     unlink("tmp/1.res");

    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
    header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
    header("Pragma: no-cache"); // HTTP/1.0
    header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT");
    echo $s;
}
?>


но, все-таки, я так и не разобрался как получить из IE частичные данные, ибо этот вариант будет сильнее тормозить сервер. Если у кого-нибудь есть какие-либо мысли, буду очень признателен их выслушать

Автор: Avb 1.11.2007, 18:11
Поддержка всех ready state-ов не гарантируется во всех браузерах

Автор: InvalidProperty 2.11.2007, 09:33
ну, это понятно, что не гарантируется, но почему тогда IE видит readyState=3, т.е. он может сказать, что вот в этот момент readyState равен 3, но данные отобразить не может.

Тогда следующий вопрос, по поводу утечек памяти браузеров, связанные с javascript. Каким образом можно догадаться, что из-за конкретного скрипта будет происходить утечка памяти? т.е. меня интересует, к примеру, создание объектов в скрипте:
xmlHttp = new XMLHttpRequest();
в этом случае браузер должен зарезервировать память, а когда он ее освободит? Или же в случае с переменными: где они создаются, на стеке или в куче, и как они уничтожаются. Еще интересует следующая конструкция:
setTimeout("some_function();", 500);
В этом случае тоже резервируется память. Но как она очищается?

Автор: InvalidProperty 5.11.2007, 02:35
всем спасибо за внимание smile мне разъяснили проблему на gotdotnet.ru http://www.gotdotnet.ru/Forums/Web/515383.aspx

исчо рас продублирую, ибо я потерял достаточно времени, чтобы локализовать проблему, будем надеяться, что после меня народ будет находить ответ на этот вопрос быстрее:

Цитата

MSDN
... oXMLHttpRequest.readyState == 3 // INTERACTIVE;
Some data has been received. Calling the responseBody and responseText properties at this state to obtain partial results will return an error, because status and response headers are not fully available.


ЗЫ Кстати, вопрос по поводу резервирования/очистки памяти javascript браузерами остается открытым. В манах говорится, что если объявлять переменную явным образом:
var a;
то в этом случае ее удаление не требуется, в отличие от неявного объявления:
a = 5;
В случае неявного объявления можно удалить переменную или объект или его свойство при помощи оператора delete, тогда не совсем понятно что будет, если не удалять... т.е. будет ли браузер по завершению обработки скрипта освобождать память? И как происходить освобождение памяти в случае с явным объявлением?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)