如何使用EventMachine在循环内与客户端通信?

时间:2013-02-06 04:05:11

标签: ruby websocket eventmachine em-websocket

我想在网站上实时显示我的节目进度(这里以循环方式示例)。

如果我运行了正确的Ruby服务器,客户端应该能够使用浏览器通过websockets连接到服务器,并且一旦连接,就会实时接收关于新生成的进程的“更新”。不需要轮询,也不需要Ajax。

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

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

main.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的通知。

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

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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