Событие XMLHttpreques onprogress не вызывается

Не путайте XMLHttprequest.onprogress с XMLHttprequest.upload.onprogress.

Я использую это событие XMLHttprequest.onprogress для обработки ввода сервера до завершения запроса на длительный опрос. На сервере скрипт может выглядеть так:

while(condition && timeout condition) {
    if(data available) {
        echo $data;
        flush();
    }
}

Событие javascript onprogress выглядит так:

  function onprogressCallback() {     
    //Start at the current position in the input, anything before has already been sent to onData()
    var seektmp = seeker;

    //Loop through the input and seek delimiters
    while(seektmp<_this.http.responseText.length&&!forcedDisconnect) {
      if(_this.http.responseText[seektmp]==_this.delimiter) {
        //If a delimiter has been found, send the fragment before to onData
        var data = _this.http.responseText.substr(seeker,seektmp-seeker); 
        //Only call on nonempty data, empty data are used to keep onprogress event running
        if(data!="")
          _this.onData(data);
        //Skip the original seeker to the end of data that has been read (+1 for delimiter)

        //console.log("DATA!: '",_this.http.responseText.substr(seeker,seektmp-seeker),"'");
        seeker=seektmp+1;   //todo: +delimiter size, instead of just 1
      }      
      //iterate 1 character, until the end of data 
      seektmp++;
    }  
  }

_this в приведенном выше коде ссылается на эту ссылку из пространства имен, которое содержит эту функцию. _this.http — это http-запрос, который я использую для длительного опроса.

Я назначаю это объекту httpreques:

this.http.onprogress = onprogressCallback;

Теперь проблема:

Элемент onprogress не вызывается, когда я вывожу небольшое количество данных один раз. Данные хранятся в каком-то буфере, и я не могу их получить, однако я вижу их в firebug.

Однако, если я продолжаю спамить браузер бесполезными данными, такими как загрузка \n, он работает так, как должен:

while(condition && timeout condition) {
    if(data available) {
        echo $data."\n";
        flush();
    }
    else {
        echo "\n";  //Endless stream of \n keeps browser calling the onprogress event
        flush();
    }
}

Но это действительно отстой. Такой вывод трудно отлаживать, и он использует много памяти.


person Tomáš Zato - Reinstate Monica    schedule 27.11.2013    source источник


Ответы (1)


У меня была такая же проблема, как у вас.

Что я мог видеть, так это то, что браузер не будет запускать событие onprogress, если он не получит минимальное количество данных. Я не знаю точно, каково это значение для всех браузеров. Но в моем случае я добавил пробел, чтобы первое сообщение имело минимальный размер 2048 символов.

Я использую что-то простое, как показано ниже (PHP)

if (strlen($data) < 2048) {
    $data = str_pad($data, 2048 - strlen($data));
}

Обратите внимание, что ваш веб-сервер может удалить дополнительные пробелы, поэтому убедитесь, что он этого не делает, если вы не видели дополнительные пробелы в браузере.

person Rafael Maiolla    schedule 15.10.2014