Fellow monks,

I am creating a Mojolicious based webapp which uses a websocket connection to periodically serve up JSON data to the client browser, which in turn uses JavaScript to render that JSON data on the webpage. My implementation assumes the following sequence of operation:

  1. User points their web browser to a static page served up by Mojolicious
  2. This static page uses JavaScript to open a websocket connection and send a single JSON packet to Mojolicious to kickstart the next step
  3. Mojolicious should periodically send JSON data back to the browser with new data
I am having problems with the last step. I think I am not understanding how Mojo::IOLoop is supposed to work. When I run my current implementation, I get one Event "read" failed: Mojo::IOLoop already running error which closes the websocket, then I get a single iteration of a delay, and then Mojolicious crashes. The documentation for Mojo is not the best, or I am missing something. Any ideas?

Here is the minimal set of code showing the problem.

use warnings; use strict; use Mojolicious::Lite; use Mojo::IOLoop; # Define which template is rendered when the client goes to the base U +RLs. get '/' => 'deleteme'; # WebSocket reading device objects websocket '/ws' => sub { my $self = shift; # Opened $self->app->log->debug('WebSocket opened.'); # Increase inactivity timeout for connection a bit my $loop = Mojo::IOLoop->singleton; $loop->stream($self->tx->connection)->timeout(1000); # Closed $self->on(finish => sub { my ($self, $code, $reason) = @_; $self->app->log->debug("WebSocket closed with status $code."); }); # Incoming message $self->on(message => sub { # safely catch abort signals local $SIG{INT} = $SIG{TERM} = $SIG{__DIE__} = $SIG{__WARN__} += sub { $self->app->log->debug("Safely caught a signal in WebSocke +t message handler"); exit 0; }; }); $self->on(json => sub { my ($self, $hash) = @_; $self->app->log->debug("Got WebSocket JSON request"); # simmulate a handful of iterations of sitting in what otherwi +se would be an infinite loop for my $i (0 .. 10) { my $delay = $loop->delay( # First delay a bit sub { my $theDelay = shift; $loop->timer(5 => $theDelay->begin); $self->app->log->debug("Delay started"); }, # next do the Read and send back the data sub { $self->app->log->debug("Doing periodic useful thin +g"); } ); $delay->wait; exit if ($i > 10); } }); }; app->start;

Here is the required supporting deleteme.html.ep file:

<!DOCTYPE html> <html> <head> <title>Test</title> %= javascript "/jquery-2.0.3.js" %= javascript "/deleteme.js" </head> <body> <center> Status of connection to <label id="connection"><%= url_with('ws')->to_abs %></labe +l> - <label id="status">Disconnected</label> </center><p/> <div id="container"></div> </body> </html>

This uses two JavaScript files. The jQuery.js is the standard source from http://jquery.com/download/. The deleteme.js is below:

$(function () { // figure out where we need to connect to, and then do so var server = $('#connection').text(); var ws = new WebSocket(server); // Figure out where to log the connection status and setup the hoo +ks to log // the current status. Also kick off the initial message to the de +vice var lblStatus = $('#status'); ws.onopen = function () { lblStatus.text('Connected'); ws.send( JSON.stringify({ obj: "AV", num: 1 }) ); }; ws.onclose = function() { lblStatus.text('Disconnected'); }; ws.onerror = function(e) { lblStatus.text('Error: ' + e.data); }; // Parse incoming response and post it to the screen ws.onmessage = function (msg) { var res = JSON.parse(msg.data); if (res.type == "name") { $("<label/>", { 'class': 'objId', 'id' : 'lbl_' + res.obj + '_' + res.num, 'text' : res.obj + res.num }).appendTo('#container'); $("<label/>", { 'class': 'objName', 'id' : 'lblName_' + res.obj + '_' + res.num, 'text' : res.value }).appendTo('#container'); } else { $("<input/>", { 'class' : 'objPv', 'name' : 'inPv_' + res.obj + '_' + res.num, 'type' : 'text', 'value' : res.value }).appendTo('#container'); } }; });

In reply to Mojolicious websocket with server-side repeating events by gri6507

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.