Javascript 服务器使用Ruby Grape发送事件

Javascript 服务器使用Ruby Grape发送事件,javascript,ruby,server-sent-events,grape,Javascript,Ruby,Server Sent Events,Grape,我正在尝试在我的服务器上创建服务器发送的事件。 问题是连接似乎总是很快关闭,因为我一直在测试网页上看到connectionclosed事件 客户端连接到服务器,因为我可以看到调用的方法,但是我想知道为什么连接不是常量,为什么我不接收使用线程发送的数据 以下是我的Ruby代码: $connections = [] class EventsAPI < Sinantra::Base def connections $connections end get "/" do

我正在尝试在我的服务器上创建服务器发送的事件。 问题是连接似乎总是很快关闭,因为我一直在测试网页上看到
connectionclosed
事件

客户端连接到服务器,因为我可以看到调用的方法,但是我想知道为什么连接不是常量,为什么我不接收使用线程发送的数据

以下是我的Ruby代码:

$connections = []

class EventsAPI < Sinantra::Base

  def connections
    $connections
  end

  get "/" do
    content_type "text/event-stream"
    stream(:keep_open) { |out|
      puts "New connection"
      out << "data: {}\n\n"
      connections << out
    }
  end

  post "/" do
    data = "data\n\n"
    connections.each { |out| out << data }
    puts "sent\n"
  end

end
编辑:我使用GET方法实现了它(我将Grape::API更改为Sinatra::Base,因为Grape没有实现流)。我现在接收数据,但连接没有保持活动状态,当我使用post方法时,数据永远不会到达浏览器


提前感谢您的回答。

JS代码看起来是正确的。我的猜测是,您不应该为无限循环启动新线程。将要发生的是,主线程将继续执行,到达其块的末尾,并关闭http请求。然后,将分离的线程留在不存在的
out
流中写入


更新以响应您的编辑:SSE不支持POST。只有使用GET Data或cookies才能将数据传递给SSE流程。

我刚刚回答了这个问题,但是如果您在葡萄API中遵循一个专门针对SSE的示例,那么发布一个指向该文档的链接将非常有用。(我特别想知道
:keep_open
到底做了什么。)我删除了循环和线程,只是为了确保我得到了数据。它可以工作(见上文),但连接不能保持活动状态。您需要无限循环:只要进程结束,SSE连接就会关闭。
  var source = new EventSource('http://localhost:9292/events');

  source.onmessage = function(e) {
      console.log("New message: ", e.data);
      showMessage(e.data);
  };

  source.onopen = function(e) {
      // Connection was opened.
  };

  source.onerror = function(e) {
      console.log("Source Error", e)
      if (e.eventPhase == EventSource.CLOSED) {
          console.log("Connection was closed");
          // Connection was closed.
      }
  };

  var showMessage = function(msg) {
      var out = document.getElementById('stream');
      var d = document.createElement('div')
      var b = document.createElement('strong')
      var now = new Date;
      b.innerHTML = msg;
      d.innerHTML = now.getHours() + ":" + now.getMinutes() + ":" +now.getSeconds() + "  ";
      d.appendChild(b);
      out.appendChild(d);
  };