Mojolicious и отложенный WebSocket

У меня есть этот фрагмент кода, я пытаюсь отправить строку на сервер каждые 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


person snoofkin    schedule 14.06.2013    source источник
comment
не могли бы вы также включить шаблоны?   -  person Joel Berger    schedule 14.06.2013


Ответы (1)


Проблема, похоже, заключается в том, что сообщение отправки пытается произойти до того, как соединение GET будет обновлено до веб-сокета. Я все еще пытаюсь отследить это, тем временем это работает.

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

Также я изменил шаблон для создания URL-адреса веб-сокета.

ОБНОВЛЕНИЕ:

Кажется, что для подключения к веб-сокету необходимо подписаться на событие. В этом примере я подписываюсь на событие завершения, которое вы все равно хотите сделать, чтобы остановить таймер.

#!/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 добавила в Mojolicious следующую документацию:

Соединение устанавливается, когда вы отвечаете на рукопожатие WebSocket со статусом ответа 101, что происходит автоматически, если вы подписываетесь на событие со значением «on» или сразу же отправляете сообщение с параметром «send».

что объясняет ситуацию. Исходный код не подписывается на событие и не делает send немедленно. Почти во всех случаях вы делаете хотя бы одно из двух, хотя в этом случае :-)

person Joel Berger    schedule 14.06.2013
comment
Спасибо. но интересно, использование url_for в шаблоне - хороший помощник Mojo, но что, если я хочу использовать защищенную схему веб-сокета (wss вместо ws, который, как я полагаю, является значением по умолчанию для Mojo????) - person snoofkin; 16.06.2013
comment
в этом случае, IIRC, вы можете сделать url_for('echo')->scheme('wss')->to_abs. url_for возвращает Mojo::URL, поэтому вы можете прочитать его документацию. - person Joel Berger; 16.06.2013