Приемник HTML5 EventSource для всех событий? - PullRequest
13 голосов
/ 30 марта 2012

У меня есть push-уведомления в моем клиентском приложении JavaScript, использующем EventSource.Я могу прикрепить прослушиватели событий следующим образом:

source.addEventListener('my_custom_event_type', function(e) {
  console.log(e.data);
}, false);

Но я хочу отслеживать все события, которые отправляются с сервера (в основном для отладки), поэтому, если какое-либо событие отправляется, но у него нет прослушивателя событий, яможет легко найти это.Я имею в виду, я не хочу просто "игнорировать" все события, которые не связаны с EventListeners.

Я бы ожидал сделать что-то вроде этого:

source.addEventListener('*', function(e) {
  console.debug('Event with no listener attached: ', e);
}, false);

Но спецификация и учебные пособиякак в html5rocks , не указывайте, возможно ли это или нет.

С другой стороны, это может быть какое-то расширение firefox / chrome, которое позволяет отслеживать все события сервера или что-то подобное.,Эти вещи действительно помогут при разработке push-уведомлений.

Спасибо!

Ответы [ 4 ]

27 голосов
/ 30 марта 2012

Я сам придумываю решение, которое также чрезвычайно улучшает интерфейс EventSource.

Серверная сторона : Не отправлять тип события, просто добавьте дополнительное поле данных (при этом я всегда использую json). Так что вместо

event: eventName
data: {mykey: 'myvalue'}

Вместо этого я отправляю это с сервера:

data: {mykey: 'myvalue', eventName: 'eventName'}

Клиентская сторона : теперь я могу использовать обратный вызов onmessage EventSource, который запускается для каждого сообщения, не имеющего тип события.

А для слушателей событий связывания я создаю класс-оболочку с функциональностью Backbone.Event. Результат:

// Server Sent Events (Event Source wrapper class)
var MyEventSource = (function() {

  function MyEventSource(url) {
    var self = this;
    _.extend(this, Backbone.Events);

    this.source = new EventSource(url);
    this.source.onmessage = function(event) {
      var data, eventName;
      var data = JSON.parse(event.data);
      var eventName = data.eventName; delete data.eventName;

      // Now we can monitor all server sent events
      console.log('app.server.on ', eventName, '. Data: ', data);

      self.trigger(eventName, data);
    };
  }

  return MyEventSource;
})();

Теперь с этим классом-оберткой я могу легко расширить функциональность, все события, отправленные сервером, можно легко отслеживать и благодаря расширению Backbone. События обработки событий в этом классе намного более мощные.

Пример использования:

var source = new MyEventSource('url/of/source');

// Add event listener
source.on('eventName', function(data) {
  console.log(data);
});

// Fire a event (also very useful for testing and debugging!!)
source.trigger('eventName', { mykey: 'myvalue' });

// Unbind event listener (very important for complex applications)
source.off('eventName');

Теперь у меня есть компонент, который легко обрабатывать, расширять, отлаживать и тестировать.

0 голосов
/ 24 мая 2019

Кредит пользователю tothemario выше за подсказку, мне нужно было это выяснить.

Похоже, что вы МОЖЕТЕ отправить события обратно в браузер с пользовательским типом, но для запуска события MESSAGE вы должны назначить слушателя для нового типа, а не типа message.

Если вы посмотрите на код на стороне клиента, приведенный ниже, мы надеемся проиллюстрировать.

Для контекста, мой сервер отправляет событие с пользовательским типом CustomType. Поэтому я подписываюсь на прослушиватель событий этого типа и добавляю еще один прослушиватель для message как ловушку для всего остального.

В этом рабочем процессе запускается событие, которое поступает в браузер с CustomType другим слушателем.

 <script type="text/javascript">
    var CustomTypeList = [];

    function EventSystemOpen(e) {
        console.log("EventSystemOpen", e);
    }

    function EventSystemError(e) {
        console.log("EventSystemOpen", e);
        if (e.readyState == EventSource.CLOSED) {
            //
        }
    }

    function GotServerEventMessage(e) {
        console.log("GotServerEventMessage", e);
    }

    function GotCustomType(e) {
        CustomTypeList.push(JSON.parse(e.data));
        console.log("Added CustomType", e, JSON.parse(e.data), CustomTypeList);
    }

    if (!!window.EventSource) {
        var source = new EventSource('api/listen');
        source.addEventListener('open', EventSystemOpen, false);
        source.addEventListener('error', EventSystemError, false);
        source.addEventListener('message', GotServerEventMessage, false);
        source.addEventListener('CustomType', GotCustomType, false);
    }
 </script>
0 голосов
/ 22 декабря 2015

Я знаю, что это не EventSource, но я искал то же самое (способ перехватить все входящие события, не зная их типа).Без какого-либо контроля над сервером, отправляющим эти события, я просто написал его с XHR, на случай, если кто-то еще столкнется с этим:

function eventStream(path, callback){
    //Create XHR object
    var xhr = new XMLHttpRequest();

    //initialize storage for previously fetched information
    var fetched='';

    //Set readystatechange handler
    xhr.onreadystatechange=function(){

        //If the connection has been made and we have 200, process the data
        if(xhr.readyState>2 && xhr.status==200){
            //save the current response text
            var newFetched=xhr.responseText;

            //this is a stream, so responseText always contains everything
            //from the start of the stream, we only want the latest
            var lastFetch=xhr.responseText.replace(fetched, '');

            //Set the complete response text to be removed next time 
            var fetched=newFetched;

            //callback to allow parsing of the fetched data
            callback(lastFetch);
        }
    };

    //open and send to begin the stream;
    xhr.open('GET', path, true);
    xhr.send();
}

parseEvents=function(response){
    var events=[];
    //split out by line break
    var lines=response.split("\n");

    //loop through the lines
    for(var i=0;i<lines.length;i++){

        //each event consists of 2 lines, one begins with
        //"name:", the other with "data"
        //if we hit data, process it and the previous line
        if(lines[i].substr(0, lines[i].indexOf(':'))=='data'){

            //add this event to our list for return
            events.push({

               //get the event name
               name: lines[i-1].split(':')[1].trim(),
               //parse the event data
               data: $.parseJSON(lines[i].substr(lines[i].indexOf(':')+1).trim())
            });
        }
    }
    //return the parsed events
    return events;
};

evenStream('http://example.com/myEventPath', function(response){
    var events=parseEvents(response);
});
0 голосов
/ 03 мая 2014
 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>  
  <script>
    var content = '';
    if(typeof(EventSource)!=="undefined")
    {
      var source = new EventSource("demo_sse.php");
      source.onmessage = function(event)
      {
        content+=event.data + "<br>";
        $("#result").html(content);
      };
    }
    else
    {
      $("#result").html("Sorry, your browser does not support server-sent events...");
    }
  </script>
...