2013-06-14 40 views
8

Tôi có đoạn mã này, tôi đang cố gắng để đẩy một chuỗi các máy chủ mỗi X giây như:Mojolicious và trì hoãn 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 sử dụng IO::Loop kiện vòng lặp, mà tôi đoán nên tốt với AnyEvent

Điều này không hiệu quả và tôi tự hỏi tại sao. Khi tôi xóa phần AE và bỏ ghi chú đơn giản send, tôi thấy kết quả trong trình duyệt.

PS: Chỉ cần thử nghiệm với WebSockets và Mojo đối với một số dự án, tôi sẽ cần phải sử dụng Cả Mojo và AnyEvent + WebSockets

+0

bạn có thể vui lòng bao gồm các mẫu không? –

+0

@JoelBerger Đã thêm – snoofkin

Trả lời

6

Vấn đề dường như là thông điệp gửi đang cố gắng để xảy ra trước khi kết nối GET được nâng cấp lên một websocket. Tôi vẫn đang cố gắng theo dõi nó, trong khi chờ đợi công trình này.

#!/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> 

thông báo rằng trong ví dụ của tôi kết xuất debug thấy 101 switching protocols trong khi ví dụ của bạn cố gắng để autorender echo.html.ep.

Ngoài ra tôi đã thay đổi mẫu để tạo url websocket.

UPDATE:

Dường như để kết nối với một WebSocket, cần thiết của nó để đăng ký vào một sự kiện. Trong ví dụ này, tôi đăng ký sự kiện kết thúc mà bạn muốn thực hiện để dừng hẹn giờ.

#!/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:

Để làm rõ vấn đề, SRI có added the following documentation to Mojolicious:

Kết nối được thiết lập khi bạn phản ứng với những cái bắt tay WebSocket với một tình trạng 101 phản ứng, tự động xảy ra nếu bạn đăng ký một sự kiện với "bật" hoặc gửi tin nhắn có "gửi" ngay lập tức.

giải thích tình huống. Mã ban đầu không đăng ký vào một sự kiện hay không ngay lập tức. Trong hầu hết các trường hợp bạn làm ít nhất một trong hai trường hợp, trong trường hợp này mặc dù :-)

+1

Cảm ơn. nhưng tự hỏi, bằng cách sử dụng url_for trong mẫu là một helper Mojo tốt đẹp, nhưng nếu tôi muốn sử dụng một lược đồ websocket bảo đảm (wss, thay vì ws mà tôi giả định là mặc định cho Mojo ????) – snoofkin

+2

trong trường hợp đó, IIRC , bạn có thể làm 'url_for ('echo') -> lược đồ ('wss') -> to_abs'. 'url_for' trả về [Mojo :: URL] (http://mojolicio.us/perldoc/Mojo/URL), vì vậy bạn có thể muốn đọc tài liệu của nó. –