1

我想在网站上实时显示我的程序的进度(此处以循环为例)。

如果我有一个适当的 Ruby 服务器正在运行,客户端应该能够使用浏览器通过 websockets 连接到服务器,并且一旦连接,就可以实时接收有关新产生的进程的“更新”。无需轮询或 Ajax。

我对此进行测试的想法是在 EventMachine::WebSocket 和使用客户端 JavaScript 的客户端浏览器之间建立双工通信。构建一个循环,并将更新发送到浏览器客户端。

ruby_socket_server.rb:

require 'eventmachine'
require 'em-websocket'
@sockets = []
EventMachine.run do
    EventMachine::WebSocket.start(:host =>'localhost',:port =>8887) do |socket|
    socket.onopen do
        @sockets << socket
        (0..10).each do |i|
            puts "i am on loop #{i}" #to terminal window
            @sockets.each do |s|
                s.send "Just received notification of loop #{i}" 
                sleep(1) #pause for a second
            end
        end
    end
end

主.js:

socket = new WebSocket('ws://localhost:8887');
socket.onopen = function(){
    console.log('OPEN');
}
socket.onclose = function(){
    console.log('CLOSED');
}
socket.onmessage = function(msg){
    console.log(msg);
}

我希望它看起来像:

  • 服务器:我在循环 1。
  • 客户:刚刚收到循环 1 的通知。
  • 服务器:我在循环 2。
  • 客户:刚刚收到循环 2 的通知。

实际发生了什么:

  • 服务器:我在循环 1。
  • 服务器:我在循环 2。
  • 客户:刚刚收到循环 1 的通知。
  • 客户:刚刚收到循环 2 的通知。

我无法从 Ruby 循环中向客户端发送数据,即它最终发送所有数据包,但不是在每次迭代期间都按预期发送。相反,它一直等到服务器循环完成,然后背靠背发送多个调用。

我在这里做错了什么?我正在寻找的东西是否可能?关于如何破解这个坚果的任何想法都会有所帮助。

4

2 回答 2

1

EventMachine 不是多线程的。所以如果你不让它运行,即如果你停留在它的任何回调中,那么什么都不会发生。

在您的示例中,您sleep在回调中调用。这将阻止回调退出,因此 EM 无法运行,如果它无法运行,则无法发送您的消息。

因此,任何 EM 服务器都必须完全围绕事件回调设置构建。

这就是为什么它被称为事件机器。它需要一种稍微不同的思维方式,但是一旦你掌握了它,你应该会没事的。

这是一个关于如何使其工作的示例:

EM.run do
  EM::WebSocket.start(:host =>'localhost',:port =>8887) do |ws|
    ws.onopen { |handshake|
      puts "New connection from #{handshake.origin}"
      loop = 1
      timer = EM.add_periodic_timer(1) {
        ws.send "Timer loop #{loop}"

        if (loop += 1) == 5
          EM.cancel_timer(timer)
          ws.send "Bye"
          ws.close_websocket
        end
      }
    }
  end
end
于 2013-02-06T06:05:34.330 回答
0

在 Rails5.0 中,您可以使用与 WebSockets 具有良好兼容性的ActionCable 。

于 2017-01-27T13:18:24.167 回答