NAME

   Mojo::AsyncAwait - An Async/Await implementation for Mojolicious

SYNOPSIS

     use Mojolicious::Lite -signatures;
     use Mojo::AsyncAwait;

     get '/' => async sub ($c) {

       my $mojo = await $c->ua->get_p('https://mojolicious.org');
       my $cpan = await $c->ua->get_p('https://metacpan.org');

       $c->render(json => {
         mojo => $mojo->result->code,
         cpan => $cpan->result->code
       });
     };

     app->start;

DESCRIPTION

   Async/await is a language-independent pattern that allows nonblocking
   asynchronous code to be structured simliarly to blocking code. This is
   done by allowing execution to be suspended by the await keyword and
   returning once the promise passed to await has been fulfilled.

   This pattern simplies the use of both promises and nonblocking code in
   general and is therefore a very exciting development for writing
   asynchronous systems.

   If you are going to use this module to create async controllers actions
   in Mojolicious applications (as seen in the "SYNOPSIS") before
   Mojolicious version 8.28, you are highly encouraged to also use
   Mojolicious::Plugin::PromiseActions in order to properly handle
   exceptions in your action.

GOALS

   The primary goal of this module is to provide a useful Async/Await
   implementation for users of the Mojolicious ecosystem. It is for this
   reason that Mojo::Promise is used when new promises are created.
   Because this is the primary goal, the intention is for it to remain
   useful even as other goals are considered.

   Secondarily, it is intended to be a testbed for early implementations
   of Async/Await in the Perl 5 language. It is for this reason that the
   implementation details are intended to be replaceable. The result
   should hopefully still be backwards compatible, mostly because the
   interface is so simple. After all, it is just two keywords.

   Of course, I always intend as much as possible that Mojolicious-focused
   code is as useful as practically possible for the broader Perl 5
   ecosystem. It is for this reason that while this module returns
   Mojo::Promises, it can accept any then-able (read: promise) which
   conforms enough to the Promises/A+ standard. The Promises/A+ standard
   is intended to increase the interoperability of promises, and while
   that line becomes more gray in Perl 5 where we don't have a single
   ioloop implementation, we try our best.

   Finally the third goal is to improve the mobility of the knowledge of
   this pattern between languages. Users of Javascript probably are
   already familiar with this patthern; when coming to Perl 5 they will
   want to continue to use it. Likewise, as Perl 5 users take on new
   languages, if they are familiar with common patterns in their new
   language, they will have an easier time learning. Having a useable
   Async/Await library in Perl 5 is key to keeping Perl 5 relevent in
   moderning coding.

BACKENDS

   This module actually does very little on its own, it simply loads and
   imports backend implementations of Async/Await. The reason to use this
   module really would be to use current default implementation without
   regards to what that implementation is nor how it works.

   When it is loaded, the MOJO_ASYNCAWAIT_BACKEND is checked, if not set
   then the current default is used.

     # From environment
     BEGIN{ $ENV{MOJO_ASYNCAWAIT_BACKEND} = '+CoolBackend' }
     use Mojo::AsyncAwait;

     # Currently provided default
     use Mojo::AsyncAwait;

   The backend is specified either as a fully qualified module name, e.g.
   Mojo::AsyncAwait::Backend::CoolBackend or using the + as a shortcut for
   Mojo::AsyncAwait::Backend::, e.g. +CoolBackend which would mean exactly
   the same as the former.

CAVEATS

   First and foremost, this is all a little bit crazy. Please consider
   carefully before using this code in production.

   While many languages have async/await as a core language feature,
   currently in Perl we must rely on modules that provide the mechanism of
   suspending and resuming execution.

   The default implementation relies on Coro which does some very magical
   things to the Perl interpreter. Other less magical implementations are
   in the works however none are available yet. As available
   implementations change or stabilize, that default may be changed.
   Backend implementations may be added or even be spun off. If your
   application depends on the backend implementation, you may import it
   manually or use the described mechanisms to load it. In that case you
   should be sure to add the backend to your dependency list in case it is
   spun off in the future.

   Also note that while a Coro-based implementation need not rely on
   "await" being called directly from an "async" function, it is currently
   prohibitied because it is likely that other/future implementations will
   rely on that behavior and thus it should not be relied upon.

KEYWORDS

   Regardless of backend, Mojo::AsyncAwait provides two keywords (i.e.
   functions), both exported by default. Depending on backend, their exact
   behavior might change slightly, however, implementers should attempt to
   follow the api described here as closely as possible.

   Some backends may allow additional options to be passed to the
   keywords; those options should be kept minimal and if possible follow
   the conventions described in Mojo::AsyncAwait::Backend::Coro. This
   generic document will not describe those additional options.

async

     my $sub = async sub { ... };

   The async keyword wraps a subroutine as an asynchronous subroutine
   which is able to be suspended via "await". The return value(s) of the
   subroutine, when called, will be wrapped in a Mojo::Promise.

   The async keyword must be called with a subroutine reference, which
   will be the body of the async subroutine.

   Note that the returned subroutine reference is not invoked for you. If
   you want to immediately invoke it, you need to so manually.

     my $promise = async(sub{ ... })->();

   If called with a preceding name, the subroutine will be installed into
   the current package with that name.

     async installed_sub => sub { ... };
     installed_sub();

   Unlike the case of an anonymous wrapped async subroutine reference
   described above, if the subroutine is installed, nothing is returned.

await

     my $tx = await Mojo::UserAgent->new->get_p('https://mojolicious.org');
     my @results = await (async sub { ...; return @async_results })->();

   The await keyword suspends execution of an async sub until a promise is
   fulfilled, returning the promise's results. In list context all promise
   results are returned. For ease of use, in scalar context the first
   promise result is returned and the remainder are discarded.

   If the value passed to await is not a promise (defined as having a then
   method), it will be wrapped in a Mojo::Promise for consistency. This is
   mostly inconsequential to the user.

   Note that await can only take one promise as an argument. If you wanted
   to await multiple promises you probably want "all" in Mojo::Promise or
   less likely "race" in Mojo::Promise.

     my $results = await Mojo::Promise->all(@promises);

AUTHORS

   Joel Berger <[email protected]>

   Marcus Ramberg <[email protected]>

CONTRIBUTORS

   Sebastian Riedel <[email protected]>

ADDITIONAL THANKS

   Matt S Trout (mst)

   Paul Evans (LeoNerd)

   John Susek

COPYRIGHT AND LICENSE

   Copyright (C) 2018, "AUTHORS" and "CONTRIBUTORS".

   This program is free software, you can redistribute it and/or modify it
   under the terms of the Artistic License version 2.0.

SEE ALSO

   Mojo::Promise

   Mojo::IOLoop

   Mojolicious::Plugin::PromiseActions

   MDN Async/Await
   <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function>

   Coro::State

   Future::AsyncAwait

   PerlX::AsyncAwait