9

私はこのコード スニペットを持っています。次のように 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 部分を削除して simple のコメントを外すとsend、ブラウザーに結果が表示されます。

PS: 一部のプロジェクトで WebSockets と Mojo を試しているところですが、Mojo と AnyEvent + WebSockets の両方を使用する必要があります。

4

1 に答える 1

7

問題は、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私の例では、例が autorender を試行している間にデバッグ出力が表示されることに注意してください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 は次のドキュメントを Mojolicious に追加しました

WebSocket ハンドシェイクに 101 応答ステータスで応答すると、接続が確立されます。これは、「on」でイベントにサブスクライブするか、「send」でメッセージをすぐに送信すると自動的に発生します。

状況を説明します。send元のコードは、イベントをサブスクライブすることも、すぐに実行することもありません。ほとんどの場合、2 つのうち少なくとも 1 つを実行しますが、この場合は :-)

于 2013-06-14T17:13:58.597 に答える