Как да говоря с клиент от рамките на цикъл с помощта на EventMachine?

Искам да покажа напредъка на моята програма (илюстриран тук като цикъл) на уебсайт в реално време.

Ако имам работещ правилен 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

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.

Не мога да изпратя данни на клиента от В рамките на Ruby цикъл, т.е. в крайна сметка той изпраща всички пакети, но не ПО ВРЕМЕ на всяка итерация, както се очаква. Вместо това, той изчаква, докато цикълът на сървъра приключи, и изпраща няколко обаждания едно след друго.

Какво правя грешно тук? Възможно ли е това, което търся? Всякакви мисли за това как да счупите този орех, биха били полезни.


person Pandem1c    schedule 06.02.2013    source източник


Отговори (2)


EventMachine не е многонишков. Така че, ако не го оставите да работи, т.е. ако останете в някое от неговите обратни извиквания, тогава нищо няма да се случи.

Във вашия пример вие извиквате sleep в обратно извикване. Това ще попречи на обратното извикване да излезе и следователно EM не може да работи, а ако не може да стартира, не може да изпрати вашето съобщение.

Така че всеки EM сървър трябва да бъде изграден изцяло около настройка за обратно извикване при събитие.

Ето защо се наричаEvent Machine. Изисква малко по-различен начин на мислене, но след като го хванете, трябва да сте добре.

Ето пример за това как можете да го накарате да работи:

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
person Casper    schedule 06.02.2013
comment
Благодаря ти!! Работи като чар. - person Pandem1c; 06.02.2013
comment
@Pandem1c - Страхотно. Не забравяйте да приемете и отговора, така че хората да знаят какво е проработило (щракнете върху отметката вляво). Благодаря. - person Casper; 06.02.2013

С Rails5.0 можете да използвате ActionCable, който има добра съвместимост с WebSockets.

person Gaurav Singh    schedule 27.01.2017