我有这个代码片段,我试图每隔X秒将字符串推送到服务器,如:
#!/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使用IO::Loop
事件循环,我认为应该可以使用AnyEvent
这不起作用,我想知道为什么。
当我删除AE部分并取消注释简单send
时,我会在浏览器中看到结果。
P.S:只是试验一些项目的WebSockets和Mojo我将需要使用Mojo和AnyEvent + WebSockets两个
答案 0 :(得分:6)
问题似乎是在GET连接升级到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;
$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>
请注意,在我的示例中,调试输出显示101 switching protocols
,而您的示例尝试自动调换echo.html.ep
。
我还更改了模板以生成websocket url。
<强>更新强>
似乎为了连接到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->on(finish => sub{ undef $w });
# $self->send(L<Mojolicious::Controller/strftime("Server $$: %a %b %e %H:%M:%S %Y", localtime));
};
app->start();
更新2:
为了澄清问题,SRI有added the following documentation to Mojolicious:
当您以101响应状态响应WebSocket握手时建立连接,如果您订阅了一个事件,则会自动发生 “开启”或立即发送“发送”消息。
解释了这种情况。原始代码既不订阅事件也不立即send
。在几乎所有情况下,你至少会做两个中的一个,但在这种情况下: - )