Acme-CPANModulesBundle-Import-MojoliciousAdvent-2018

 view release on metacpan or  search on metacpan

devdata/https_mojolicious.io_blog_2018_12_20_testing-dancer_  view on Meta::CPAN

<p>During advent last year, I wrote about <a href="https://mojolicious.org/perldoc/Test/Mojo">Test::Mojo</a>, showing the many easy and (dare I say) fun ways that you can use it to test your Mojolicious applications.
If you missed it, go <a href="https://mojolicious.io/blog/2017/12/09/day-9-the-best-way-to-test/">check it out</a>.</p>

<p>I expect there are at least a few of you out there who read that and think, &quot;I&#39;d love to use that, but I don&#39;t use Mojolicious!&quot;; well, you&#39;re in luck!
With just a little role to bridge the gap, you can use Test::Mojo to test your PSGI applications too!</p>

              </section>
              <section id="section-2">
                  <h2>Mounting PSGI Applications</h2>

<p>Mojolicious itself doesn&#39;t use the <a href="https://metacpan.org/pod/PSGI">PSGI</a> protocol, owing to certain features that it doesn&#39;t provide and which are necessary for certain asynchronous operations.
That said, you can serve a Mojolicious application on a PSGI server by using <a href="https://mojolicious.org/perldoc/Mojo/Server/PSGI">Mojo::Server::PSGI</a>.
This Mojolicious-core module is automatically used for you when your Mojolicious-based app detects that it has started under a PSGI server (e.g. plackup or Starman).</p>

<p>While translating between a Mojo app and a PSGI server is core functionality, doing the opposite, translating between a PSGI app and a Mojolicious server (or app, as you&#39;ll see) is available as a third party module.
<a href="https://metacpan.org/pod/Mojolicious::Plugin::MountPSGI">Mojolicious::Plugin::MountPSGI</a>, as it&#39;s name implies, can mount a PSGI application into a Mojolicious-based one.
To do so, it builds a new, empty Mojolicious application that translates all requests to PSGI environments before dispatching to it as with any <a href="https://mojolicious.org/perldoc/Mojolicious/Plugin/Mount">mount</a>-ed application.</p>

<h2>Testing using Test::Mojo</h2>

<p>Once you can do that, it is trivial to take a PSGI application, wrap it with MountPSGI, and set it as the application for use with Test::Mojo.

devdata/https_mojolicious.io_blog_2018_12_24_async-await-the-mojo-way_  view on Meta::CPAN

            </div>

              <div class="post-thumb">
                <!-- theme suggests 1300x500 -->
                <img alt="Vancouver Symphony Orchestra with Bramwell Tovey" src="/blog/2018/12/24/async-await-the-mojo-way/banner.jpg">
              </div>

            <div class="post-content">

              <section id="section-1">
                  <h2>The Problems with Thinking in Asynchronous Code</h2>

<p>I&#39;ve thought a lot about asynchronous code.
Learning it, writing it, teaching it.
Async is hard.</p>

<blockquote>
  <p>Learning async programming is about being completely confused and overcomplicating everything and eventually having an &#39;aha&#39; moment and then being utterly frustrated you don&#39;t have a way to teach other people without them needing to ...
  <cite><a href="https://shadow.cat/blog/matt-s-trout/">Matt S. Trout</a></cite></p>
</blockquote>

<p>While Matt is right, I&#39;ve thought a lot about that quote and I think I&#39;ve come up with an underlying problem.
This may sound trite and it may seem obvious, but the problem is that writing asynchronous code is just fundamentally different than writing blocking code.</p>

<p>We&#39;ve always known how to make one instruction follow another, that&#39;s easy, it happens on the next line of code.
Line one executes and then line two.
If line two needs something from line one it will be there.</p>

<p>Say you want to write &quot;get this web resource, then print the title&quot;.
In blocking code that is easy!</p>

<pre><code>use Mojo::Base -strict, -signatures;
use Mojo::UserAgent;
use Mojo::Util &#39;trim&#39;;
my $ua = Mojo::UserAgent-&gt;new;

my $title = trim $ua-&gt;get($url)-&gt;res-&gt;dom-&gt;at(&#39;title&#39;)-&gt;text;
say $title;
</code></pre>

<p>In asynchronous code, those two steps don&#39;t just follow in sequence, either in execution in the file nor in actual code flow.
A newcomer to nonblocking is told that to make that nonblocking, you need a callback; a thing to do once the transaction is complete.
So they might write this (non-working!) code instead.</p>

<pre><code>use Mojo::Base -strict, -signatures;
use Mojo::IOLoop;
use Mojo::UserAgent;
use Mojo::Util &#39;trim&#39;;
my $ua = Mojo::UserAgent-&gt;new;
my $url = &#39;https://mojolicious.org&#39;;

devdata/https_mojolicious.io_blog_2018_12_24_async-await-the-mojo-way_  view on Meta::CPAN

<h2>Conclusion</h2>

<p>So now the formula is simple.</p>

<ul>
<li>Use libraries that return promises rather than take callbacks.</li>
<li>Use the <code>async</code> keyword when declaring functions that need to <code>await</code> promises.</li>
<li>Organize your promises using <a href="https://mojolicious.org/perldoc/Mojo/Promise#all">all</a>, <a href="https://mojolicious.org/perldoc/Mojo/Promise#race">race</a> (only wait for the first resolved promise) or some <a href="https://mojolicious....
</ul>

<p>Hopefully with Mojo::AsyncAwait, writing asynchronous code is finally going to be accessible to those users that haven&#39;t yet had Matt&#39;s &quot;aha&quot; moment.
And for those of us who have, don&#39;t worry, you&#39;ll love it too.</p>

<p><em>Another excellent resource is <a href="https://www.youtube.com/watch?v=gB-OmN1egV8">The Evolution of Async JavaScript: From Callbacks, to Promises, to Async/Await</a> by Tyler McGinnis.
It is for JavaScript, but nearly everything applies except they syntax.
Highly recommended.</em></p>

              </section>
              <small><p><a href="https://commons.wikimedia.org/w/index.php?curid=15521095">Banner image</a> by <a href="https://www.flickr.com/people/56355577@N06">Vancouver 125 - The City of Vancouver</a> <a href="https://www.flickr.com/photos/vanco...
</small>



( run in 0.229 second using v1.01-cache-2.11-cpan-0d8aa00de5b )