JavaScript EventSource SSE未在浏览器中触发

Dan*_*Dan 22 javascript html5 node.js server-sent-events

我一直在开发一个nodejs服务器,为我在HTML5中开发的新网站提供服务器端事件.

当我telnet到服务器它正常工作,向我发送所需的HTTP响应标头,然后是我目前每2或3秒生成一次事件流,以证明它的工作原理.

我已经尝试了最新版本的FireFox,Chrome和Opera,他们创建了EventSource对象并连接到nodejs服务器,但是没有一个浏览器生成任何事件,包括onopen,onmessage和onerror.

但是,如果我停止我的nodejs服务器,终止与浏览器的连接,他们都会突然发送所有消息,并显示我的所有事件.然后浏览器都按照规范尝试重新连接到服务器.

我在网络服务器上托管所有内容.没有在本地文件中运行.

我已经阅读了我在网上找到的所有内容,包括我购买的书籍,没有任何迹象表明存在此类问题.我有什么遗失的东西吗?

示例服务器实现

  var http = require('http');
  var requests = [];

  var server = http.Server(function(req, res) {
    var clientIP = req.socket.remoteAddress;
    var clientPort = req.socket.remotePort;

    res.on('close', function() {
      console.log("client " + clientIP + ":" + clientPort + " died");

      for(var i=requests.length -1; i>=0; i--) {
        if ((requests[i].ip == clientIP) && (requests[i].port == clientPort)) {
          requests.splice(i, 1);
        }
      }
    });

    res.writeHead(200, {
      'Content-Type': 'text/event-stream', 
      'Access-Control-Allow-Origin': '*', 
      'Cache-Control': 'no-cache', 
      'Connection': 'keep-alive'});

    requests.push({ip:clientIP, port:clientPort, res:res});

    res.write(": connected.\n\n");
  });

  server.listen(8080);

  setInterval(function test() {
    broadcast('poll', "test message");
  }, 2000);

function broadcast(rtype, msg) {
  var lines = msg.split("\n");

  for(var i=requests.length -1; i>=0; i--) {
    requests[i].res.write("event: " + rtype + "\n");
    for(var j=0; j<lines.length; j++) {
      if (lines[j]) {
        requests[i].res.write("data: " + lines[j] + "\n");
      }
    }
    requests[i].res.write("\n");
  }
}
Run Code Online (Sandbox Code Playgroud)

一个示例html页面

<!DOCTYPE html>
<html>
  <head>
    <title>SSE Test</title>
    <meta charset="utf-8" />
    <script language="JavaScript">
      function init() {
        if(typeof(EventSource)!=="undefined") {
          var log = document.getElementById('log');
          if (log) {
            log.innerHTML = "EventSource() testing begins..<br>";
          }

          var svrEvents = new EventSource('/sse');

          svrEvents.onopen = function() {
            connectionOpen(true);
          }

          svrEvents.onerror = function() {
            connectionOpen(false);
          }

          svrEvents.addEventListener('poll', displayPoll, false);             // display multi choice and send back answer

          svrEvents.onmessage = function(event) {
              var log = document.getElementById('log');
              if (log) {
                log.innerHTML += 'message: ' + event.data + "<br>";
              }
            // absorb any other messages
          }
        } else {
          var log = document.getElementById('log');
          if (log) {
            log.innerHTML = "EventSource() not supported<br>";
          }
        }
      }

      function connectionOpen(status) {
          var log = document.getElementById('log');
          if (log) {
            log.innerHTML += 'connected: ' + status + "<br>";
          }
      }

      function displayPoll(event) {
        var html = event.data;
          var log = document.getElementById('log');
          if (log) {
            log.innerHTML += 'poll: ' + html + "<br>";
          }
      }
    </script>
  </head>
  <body onLoad="init()">
    <div id="log">testing...</div>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

这些示例是基本的,但与我在书籍和在线中看到的每个其他演示具有相同的变化.如果我结束客户端连接或终止服务器,eventSource似乎只能工作,但这将是轮询而不是SSE,我特别想使用SSE.

有趣的是,当我在网上使用它们时,来自html5rock的这些演示似乎也没有按预期工作.

Dan*_*Dan 37

破解了!:)

感谢Tom Kersten帮助我进行测试的一些帮助.原来代码不是问题.

请注意..如果您的客户使用任何拦截Web请求的防病毒软件,可能会导致此处出现问题.在这种情况下,提供企业级防病毒和防火墙保护的Sophos Endpoint Security具有称为Web保护的功能.在此功能中可以选择扫描下载; 似乎SSE连接被视为下载,因此在关闭连接并接收流以进行扫描之前,不会将其释放到浏览器.禁用此选项可以解决问题.我提交了一份错误报告,但其他反病毒系统也可能会这样做.

感谢您的建议并帮助大家:)