One more thing: you need to keep a strong reference to the Mojo::UserAgent
object until it completes, so you should define $ua outside of the action
method which will end before the async code occurs.

-Dan

On Thu, Feb 7, 2019 at 1:23 PM Dan Book <gri...@gmail.com> wrote:

> Your commented 'for' loop is correct; you need to dereference
> stash('titles') to pass the list of hashrefs to the loop. The other problem
> is that you need to prevent auto-rendering until your async code has
> completed. You can do this by calling `$c->render_later` at the beginning
> of the action (`$c` is the first argument passed to the action, which you
> need to retrieve), and then `$c->render` after you've set the stash value.
> You can even include the stash update in the render call:
> `$c->render(titles => $titles);`
>
> I would additionally recommend to use promises rather than delays as it
> will lead to much more concise code with the promise methods available from
> Mojo::UserAgent. Also, you want to hold a reference to the transaction, and
> add exception handling, as described here:
> https://github.com/mojolicious/mojo/wiki/Upgrading#delay-helper-removed
>
> Here is how it might look as a start:
>
> get '/titles' => sub {
>     my $c = shift;
>     $c->render_later;
>     my $tx = $c->tx;
>     my $ua    = Mojo::UserAgent->new;
>     my @promises = map { $ua->get_p($_) } @urls;
>     Mojo::Promise->all(@promises)->then(sub {
>         my @results = @_;
>         my $titles = [];
>         foreach my $result (@results) {
>             my $tx = $result->[0];
>             my $title = trim($tx->res->dom->at('title')->text);
>             push @$titles, {host => $tx->req->url->host, title => $title};
>         }
>         $c->render(titles => $titles);
>     })->catch(sub { $c->reply->exception(pop); undef $tx });
> } => 'titles';
>
> -Dan
>
> On Thu, Feb 7, 2019 at 12:57 PM Ron Bergin <rkber...@gmail.com> wrote:
>
>> Note: I cross posted this question on perlmonks
>> https://perlmonks.org/?node_id=1229558
>>
>> On Thursday, February 7, 2019 at 9:48:20 AM UTC-8, Ron Bergin wrote:
>>>
>>> I'm brand new to Mojolicious and working on a lite script that goes to
>>> 75 urls and retrieves text in an h3 tag. I've worked up a working test
>>> script that outputs to console and now I'm working on adjusting it to be a
>>> web app but I can't seem to get the correct syntax to store/retrieve the
>>> data.  What am I doing wrong?
>>>
>>> #!/usr/bin/perl
>>>
>>> use Mojolicious::Lite;
>>>
>>> my @urls  = (
>>>     'https://mojolicious.org',
>>>     'https://metacpan.org',
>>>     'https://perlmonks.org',
>>>     'http://www.google.com',
>>> );
>>>
>>> get '/titles' => sub {
>>>     my $ua    = Mojo::UserAgent->new;
>>>     my $async = Mojo::IOLoop::Delay->new;
>>>
>>>     $async->steps(
>>>         sub {
>>>             my $self = shift;
>>>             $ua->get($_, $self->begin) for @urls;
>>>         },
>>>         sub {
>>>             my ($self, @tx) = @_;
>>>             my $titles      = [];
>>>
>>>             foreach (@tx) {
>>>                 my $title  = '';
>>>                 my $status = $_->res->is_success ? 'Connected' : $_->
>>> error->{message};
>>>
>>>                 if ( $_->res->is_success ) {
>>>                     $title = $_->res->dom->at('title')->text;
>>>                     $title =~ s/^\s+|\s+$//g; # couldn't get Mojo::Util
>>> trim function to work
>>>                 }
>>>
>>>                 push @$titles, {host => $_->req->url->host, status =>
>>> $status, title => $title};
>>>             }
>>>             $self->stash(titles => $titles);
>>>         }
>>>     );
>>> } => 'titles';
>>>
>>> app->start;
>>>
>>> __DATA__
>>>
>>> @@ titles.html.ep
>>> % layout 'titles';
>>>
>>> %= dumper stash('titles')
>>>
>>> <table border=1>
>>> <tr>
>>>   <th>Host</th>
>>>   <th>Status</th>
>>>   <th>Title</th>
>>> </tr>
>>>
>>> <!-- % for my $server ( @{ stash('titles') } ) { -->
>>> % for my $server ( stash('titles') ) {
>>>   <tr>
>>>     <td><%= $server->{host} %></td>
>>>     <td><%= $server->{status} %></td>
>>>     <td><%= $server->{title} =%></td>
>>>   </tr>
>>> % }
>>> </table>
>>>
>>> @@ layouts/titles.html.ep
>>> <!doctype html>
>>>
>>> <html>
>>>
>>> <head>
>>>   <title>Titles</title>
>>> </head>
>>>
>>> <body>
>>> <h1>Titles</h1>
>>> <%= content =%>
>>> </body>
>>>
>>> </html>
>>>
>>>
>>> Here's the output:
>>>
>>>> $ ./titles_web.pl get /titles
>>>> [Thu Feb  7 09:45:54 2019] [debug] GET "/titles" (fcf21ce8)
>>>> [Thu Feb  7 09:45:54 2019] [debug] Routing to a callback
>>>> [Thu Feb  7 09:45:54 2019] [debug] Rendering template "titles.html.ep"
>>>> from DATA section
>>>> [Thu Feb  7 09:45:54 2019] [debug] Rendering template
>>>> "layouts/titles.html.ep" from DATA section
>>>> [Thu Feb  7 09:45:54 2019] [debug] 200 OK (0.00267s, 374.532/s)
>>>> <!doctype html>
>>>>
>>>> <html>
>>>>
>>>> <head>
>>>>   <title>Titles</title>
>>>> </head>
>>>>
>>>> <body>
>>>> <h1>Titles</h1>
>>>>
>>>> undef
>>>>
>>>>
>>>> <table border=1>
>>>> <tr>
>>>>   <th>Host</th>
>>>>   <th>Status</th>
>>>>   <th>Title</th>
>>>> </tr>
>>>>
>>>> <!-- % for my $server ( @{ stash('titles') } ) { -->
>>>>   <tr>
>>>>     <td></td>
>>>>     <td></td>
>>>>     <td></td>
>>>> </tr>
>>>> </table>
>>>> </body>
>>>>
>>>> </html>
>>>>
>>>
>>> --
>> You received this message because you are subscribed to the Google Groups
>> "Mojolicious" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to mojolicious+unsubscr...@googlegroups.com.
>> To post to this group, send email to mojolicious@googlegroups.com.
>> Visit this group at https://groups.google.com/group/mojolicious.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Mojolicious" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mojolicious+unsubscr...@googlegroups.com.
To post to this group, send email to mojolicious@googlegroups.com.
Visit this group at https://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

Reply via email to