2013-06-14 11 views
8

Mam ten fragment kodu, próbuję naciskać ciąg na serwer co X sekund, takie jak:Mojolicious i opóźnione websocket

#!/usr/bin/env perl 
use Mojolicious::Lite; 
use EV; 
use AnyEvent; 
use POSIX qw(strftime); 

get '/' => sub { 
    my $self = shift; 

    $self->render('main'); 
}; 

websocket '/echo' => sub { 
     my $self = shift; 
     my $w; 
     $w = AE::timer 3, 1, sub { 
        $self->send('Got it'); 
     }; 
     # $self->send(strftime("Server $$: %a %b %e %H:%M:%S %Y", localtime)); 
}; 
app->start(); 

__DATA__ 
@@ main.html.ep 
<html> 
<head> 
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> 
</head> 
<body> 
<table id="tableID"> 
<tbody> 
</tbody> 
</table> 
<script type="text/javascript"> 
var ws = new WebSocket('ws://192.168.1.104:3000/echo'); 
     ws.onopen = function() { 
     alert('Connection opened'); 
     }; 
     ws.onerror = function() { alert("Error"); }; 
     ws.onmessage = function (msg) { 
      $("#tableID").find('tbody') 
         .append($('<tr>') 
         .append($('<td>') 
         .text(msg.data) 
      ) 
     ); 

     }; 
</script> 
</body> 
</html> 

AFAIK Mojo wykorzystywane IO::Loop pętlę zdarzeń, co chyba powinno być w porządku AnyEvent

To nie działa i zastanawiam się, dlaczego. Po usunięciu części AE i odkomentowaniu prostego send, widzę wyniki w przeglądarce.

PS: Wystarczy eksperymenty z WebSocket i Mojo jakiegoś projektu będzie trzeba używać obu Mojo i AnyEvent + WebSockets

+0

można proszę zawierać szablony też? –

+0

@JoelBerger Dodano – snoofkin

Odpowiedz

6

Problem wydaje się być to, że wyślij wiadomość stara się wydarzy, zanim połączenie GET zostanie uaktualniony do websocket. Nadal próbuję go wyśledzić, w międzyczasie to działa.

#!/usr/bin/env perl 
use Mojolicious::Lite; 
use EV; 
use AnyEvent; 
#use POSIX qw(strftime); 

get '/' => sub { 
    my $self = shift; 

    $self->render('main'); 
}; 

websocket '/echo' => sub { 
     my $self = shift; 
     my $w; 

     $self->on(finish => sub { Mojo::IOLoop->remove($w) }); 
     # $self->send(strftime("Server $$: %a %b %e %H:%M:%S %Y", localtime)); 

     $w = Mojo::IOLoop->recurring(1 => sub{ 
        $self->send('Got it'); 
     }); 
}; 
app->start(); 

__DATA__ 
@@ main.html.ep 
<html> 
<head> 
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> 
</head> 
<body> 
<table id="tableID"> 
<tbody> 
</tbody> 
</table> 
<script type="text/javascript"> 
var ws = new WebSocket("<%= url_for('echo')->to_abs %>"); 
     ws.onopen = function() { 
     alert('Connection opened'); 
     }; 
     ws.onerror = function() { alert("Error"); }; 
     ws.onmessage = function (msg) { 
      $("#tableID").find('tbody') 
         .append($('<tr>') 
         .append($('<td>') 
         .text(msg.data) 
      ) 
     ); 

     }; 
</script> 
</body> 
</html> 

zauważyć, że w moim przykładzie wyjście debugowania pokazuje 101 switching protocols Twój przykład podczas próby autorender echo.html.ep.

Zmieniłem również szablon, aby wygenerować URL strony internetowej.

UPDATE:

Wydaje się, że w celu podłączenia do websocket jej niezbędne do subskrybowania zdarzenia. W tym przykładzie zapisuję się do zdarzenia zakończenia, które i tak chcesz zrobić, aby zatrzymać stoper.

#!/usr/bin/env perl 
use Mojolicious::Lite; 
use EV; 
use AnyEvent; 
#use POSIX qw(strftime); 

get '/' => sub { 
    my $self = shift; 

    $self->render('main'); 
}; 

websocket '/echo' => sub { 
     my $self = shift; 
     my $w; 
     $w = AE::timer 3, 1, sub { 
        $self->send('Got it'); 
     }; 
     $self->on(finish => sub{ undef $w }); 
     # $self->send(L<Mojolicious::Controller/strftime("Server $$: %a %b %e %H:%M:%S %Y", localtime)); 
}; 
app->start(); 

UPDATE 2:

W celu wyjaśnienia problemu, SRI ma added the following documentation to Mojolicious:

Połączenie zostanie ustalone, gdy odpowiesz na uzgadniania websocket ze statusem 101 odpowiedzi, co dzieje się automatycznie, jeśli subskrybujesz wydarzenie z "na" lub wyślij wiadomość z "wyślij" od razu.

co wyjaśnia sytuację. Oryginalny kod nie subskrybuje zdarzenia ani nie jest natychmiastowy. W prawie wszystkich przypadkach to zrobić co najmniej jeden z dwóch, chociaż w tym przypadku :-)

+1

Dzięki. ale zastanawiasz się, używając url_for w szablonie jest miły Mojo pomocnik, ale co zrobić, jeśli chcę użyć zabezpieczonego systemu websocket (WSS, zamiast ws które zakładam jest domyślny dla Mojo ????) – snoofkin

+2

w tym przypadku, IIRC możesz zrobić 'url_for ('echo') -> scheme ('wss') -> to_abs'. 'url_for' zwraca [Mojo :: URL] (http://mojolicio.us/perldoc/Mojo/URL), więc możesz chcieć przeczytać jego dokumentację. –

Powiązane problemy