HTML5 Функция данных EventSource обрабатывает предыдущее значение, а не текущее - PullRequest
1 голос
/ 12 января 2020

Я настроил http-сервер для отправки данных с интервалом в 20 секунд. Данные начинаются с 101, и это число увеличивается каждый раз. Таким образом, последовательность чисел будет 101,102,103 и т. Д. c

. Я также добавляю данные после a; разделитель, отметка времени, когда сервер отправляет данные.

Я думаю, что у меня есть ошибка в моем коде javascript, потому что я наблюдаю это поведение:

http-сервер отправляет данные "105" в 12: 28: 52.654

на моей веб-странице я вижу элемент данных «105» в 12: 29: 12: 690, ie 20 секунд спустя. 20 секунд - это интервал отправки данных. Таким образом, похоже, что функция onmessage EventSource вызывается, но обрабатывает предыдущий элемент данных, в данном случае «104».

Код веб-страницы:

<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">

let source = new EventSource('/startmonitoring');

function startCallMonitoring(){
     source.onmessage = function(event) {
      console.log(event.data);
      addCall(event.data);
    };

     source.addEventListener('error', function(e) {
    if (e.readyState == EventSource.CLOSED) {
        console.log("closed");
    }
    }, false);

}

function stopCallMonitoring() {
  source.close();
}

function gettime() {
  var currentDate = new Date();
  var hour = currentDate.getHours();
  var minute = currentDate.getMinutes();
  var second = currentDate.getSeconds();
  var millisecond = currentDate.getMilliseconds();
  return pad(hour) + ":" + pad(minute) + ":" + pad(second) + "." + millisecond;
}

function getdate() {
  var currentDate = new Date();
  var date = currentDate.getDate();
  var month = currentDate.getMonth(); //Be careful! January is 0 not 1
  var year = currentDate.getFullYear();
  return pad(date) + "/" + pad(month + 1) + "/" + pad(year);
}

function pad(n) {
    return n<10 ? '0'+n : n;
}

function addCall(callerid) {
  // insert new row.
  var tableref = document.getElementById('CallsTable').getElementsByTagName('tbody')[0];
  var newrow = tableref.insertRow(0);
  var datecell = newrow.insertCell(0);
  var timecell = newrow.insertCell(1);
  var calleridcell = newrow.insertCell(2);
  var customerlinkcell = newrow.insertCell(3);
  datecell.innerHTML = getdate();
  timecell.innerHTML = gettime();
  calleridcell.innerHTML = callerid;
  customerlinkcell.innerHTML = "customerlink";
  console.log("added " + callerid + " at " + gettime());
}

</script>

</head>
<body>">

  <button onclick="startCallMonitoring()">Start Call Monitoring</button>
  <button onclick="stopCallMonitoring()">Stop Call Monitoring</button>

<table id="CallsTable">
    <thead>
        <tr>
          <th>Date</th>
             <th>Time added to table</th>
             <th>CallerID</th>
             <th>link</th>
        </tr>
    </thead>
    <tbody>
        <tr>
        </tr>
    </tbody>
</table>

</body>
</html>

Снимок экрана потока событий в Chrome средствах разработки.

screenshot

Почему такое поведение? Как я могу это исправить?

Дополнительная информация о серверной части.

Я сам написал http-сервер, чтобы это могло быть причиной. Без отправки всего кода для сервера, который является довольно большим, вот код, использующий некоторые вспомогательные функции для создания ответного сообщения HTTP.

Этот timerfun c вызывается каждые 20 секунд.

Обычно, когда я вижу в консоли сервера вывод:

timerfunc() - sending: HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 29
Cache-Control: no-cache
Content-Type: text/event-stream
Access-Control-Allow-Origin: *

id: 7
data: 106;12:29:12.689
 to 192

Затем в веб-браузере заполняется элемент данных 105.

void http_server::timerfunc() {

    http_response rs;
    rs.status = 200;
    rs.set_version(1, 1);
    rs.add_header("Connection", "keep-alive");
    rs.add_header("Content-Type", "text/event-stream");  // this is REQUIRED
    //header('Cache-Control: no-cache');
    rs.add_header("Cache-Control", "no-cache");        // not sure if required, investigate what it does
    rs.add_header("Access-Control-Allow-Origin", "*");  // think because for node.js demo was on different network - don't think need this
    //rs.add_header("Transfer-Encoding", "chunked");  // doesn't work if you don't do chunking - investigate - but don't need

    static unsigned number = 100;
    std::string callerid = std::to_string(number);

    char timebuf[50] = {};
    get_timestamp(timebuf);

    rs.set_body("id: 7\ndata: " + callerid + ";" + timebuf + "\n");
    rs.set_content_length_to_body_length();

    unsigned retcode = 0;

    const size_t len = rs.get_content_length();
    for (auto client : clients) {
        std::string s = codec.make_http_response_message(rs);
        retcode = send(client, s.c_str(), s.length());

        std::cout << "timerfunc() - sending: " << s << " to " << client << std::endl;
    }
    number++;

    if (number == 999)
        number = 100;

}

1 Ответ

0 голосов
/ 16 января 2020

Я подумал, что было бы полезно опубликовать sh, как я в итоге исправил проблему.

Это не имело никакого отношения к клиенту. Мне пришлось внести следующие изменения в веб-сервер, отправляющий событие, чтобы оно полностью заработало:

  1. Изменить заголовок в запросах с полезной нагрузкой события на Transfer-Type: chunked.
  2. Полезная нагрузка запроса должен использовать чанкованный формат \ r \ n \ r \ n0 \ r \ n
  3. Для событий, отправляемых сервером, поток данных для отправки должен начинаться с "data:"

Итак, если вы хотите отправить «Мои прекрасные потоковые данные, часть 1» в виде потокового сообщения, сообщение http будет выглядеть так:

HTTP/1.1 200 OK\r\n
Connection: Keep-Alive\r\n
Date: Wed, 15 Jan 2020 18:40:24 GMT\r\n
Content-Type: text/event-stream\r\n
Transfer-Encoding: chunked\r\n
Cache-Control: no-cache\r\n
\r\n
24\r\n
data: My lovely streamed data part 1\r\n
0\r\n

Не уверен, что требуется заголовок Cache-Control.

Веб-сервер может отправлять несколько сегментов текста с добавлением длины, затем \ r \ n, затем строки, а затем \ r \ n.

Подробнее о кодировке передачи здесь: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding

...