html - 有趣且延迟的 WebSocket

标签 html perl websocket mojolicious

我有这个代码片段,我试图每隔 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

最佳答案

问题似乎是发送消息试图在 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,必须订阅一个事件。在此示例中,我订阅了 finish 事件,您无论如何都想这样做以停止计时器。

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

The connection gets established when you respond to the WebSocket handshake with a 101 response status, which happens automatically if you subscribe to an event with "on" or send a message with "send" right away.

这说明了情况。原始代码既不订阅事件也不立即发送 。在几乎所有情况下,您至少会执行两者之一,但在这种情况下 :-)

关于html - 有趣且延迟的 WebSocket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17113399/

相关文章:

ruby-on-rails - websocket 握手期间的 Rails ActionCable 错误

node.js - 无法在 websocket ping 中调用 redis.get() 函数

stream - 从客户端到服务器的视频流 : which alternative use, websocket 或 webrtc

javascript - 读取多个文件后的回调函数

javascript - 为什么当我尝试通过添加类来使用 jQuery 隐藏我的 CSS 三 Angular 形时它不起作用?

regex - 使用正则表达式匹配字符串中的连续字符

perl - 为什么拆分不返回任何东西?

windows - 如果 Windows,如何跳过子测试中的所有测试?

html - 像 StackOverflow 一样的响应式导航栏

html - iframe { 高度 :70%;} not working in IE 8 and Firefox