perlmojoliciousmojolicious-lite

Do something after rendering in mojolicious


How can I make my code do something after HypnoToad sends a page? (Note: I am answering my own question. I am posting this, because StackOverflow pointed me to a previous question that did not directly solve my problem, although it did contain the clue that I needed.)

Example code:

use Mojolicious::Lite;
get "/index" => sub {
   my $c = shift;
   $c->render("renderThis");
   # Do something after rendering
};
app->start('daemon', '-l', 'http://*:8080');

__DATA__
@@ renderThis.html.ep
% layout  "template" ;
<h1>Hello World</h1>

@@ layouts/template.html.ep
<!DOCTYPE html>
<html><head></head><body>
%= content
</body></html>

render seems to buffer its http output and sends it after the code block is finished. I want something to execute after the page gets sent. The buffering can be observed by putting the following in place of the "Do something" comment.

   sleep 15;
   say "Wow, that was a long time!";

I am on win7, so a unix-only solution won't work.


Solution

  • You can attach code to the finish event on the transaction. Most other methods would not be guaranteed to wait until the response has actually been sent, since it happens in an asynchronous fashion.

    use Mojolicious::Lite;
    get "/index" => sub {
       my $c = shift;
       $c->render("renderThis");
       $c->tx->on(finish => sub {
          sleep 15; # this is a really bad idea, use a timer instead
          say "That was a long time, but at least the page got sent quickly.";
       });
    };