The best approach would probably be to rethink your logic to be fully asynchronous. You should not ever need to wait for results; you should always do the following actions in further ->then callbacks, or use Mojo::Promise->all or similar to make promises that wait for several other promises.
-Dan On Thu, Mar 15, 2018 at 12:51 AM, Michael Fung <[email protected]> wrote: > This is gold: > *"You need to use the same event loop for the promise as for the items > that will resolve it"* > > Thanks Dan! > > The posted action is just for demo my problem. I actually want to use a > loop to do something like: > > # inside a timer callback > my $more_jobs = 1; > while ($more_jobs) { > $get_job->() > ->then( $run_job ) > ->catch( sub { $more_jobs = 0 } ) > ->wait; > } > > > > > On Thursday, March 15, 2018 at 12:35:16 PM UTC+8, Dan Book wrote: >> >> But to add, there's usually no reason to make it this complicated; if you >> just use the main event loop, and do your rendering in a ->then chained off >> the promise, you don't need to wait for it; it will render the page when >> the promise resolves. >> >> On Thu, Mar 15, 2018 at 12:34 AM, Dan Book <[email protected]> wrote: >> >>> You need to use the same event loop for the promise as for the items >>> that will resolve it. So for instance in your example you need to do: >>> >>> my $loop = Mojo::IOLoop->new; >>> my $promise = Mojo::Promise->new(ioloop => $loop); >>> $loop->timer(...); >>> return $promise; >>> >>> On Wed, Mar 14, 2018 at 11:34 PM, Michael Fung <[email protected]> >>> wrote: >>> >>>> Hi Dan, >>>> >>>> It does not work, perhaps I misunderstood you. >>>> >>>> Here is my action for test: >>>> >>>> sub boom { >>>> my ($c) = @_; >>>> my @output; >>>> >>>> >>>> my $timer = sub { >>>> #~ my $promise = Mojo::Promise->new; >>>> my $promise = Mojo::Promise->new(ioloop => Mojo::IOLoop->new); >>>> Mojo::IOLoop->timer( 2 => sub { >>>> $promise->resolve(); >>>> }); >>>> return $promise; >>>> }; >>>> >>>> >>>> $timer->() >>>> ->then( sub { >>>> warn "Boom!"; >>>> push @output, "Boom!"; >>>> } ) >>>> ->wait; >>>> >>>> push @output, "-the end- \n"; >>>> >>>> >>>> $c->render(text => join(",", @output) ); >>>> } >>>> >>>> >>>> >>>> No matter which Mojo::Promise->new statement I use, the result is the >>>> same: I only get "-the end-" without "Boom!". >>>> >>>> >>>> On Thursday, March 15, 2018 at 12:21:12 AM UTC+8, Dan Book wrote: >>>>> >>>>> ->wait will not block if the event loop is currently running, like if >>>>> you are setting this up in an event loop callback like a request handler. >>>>> In order to cause promises to block while running the main event loop, you >>>>> need to run the promises in a separate event loop. >>>>> >>>>> my $promise = Mojo::Promise->new(ioloop => Mojo::IOLoop->new); >>>>> >>>>> On Wed, Mar 14, 2018 at 10:06 AM, Michael Fung <[email protected]> >>>>> wrote: >>>>> >>>>>> Thanks Andre. I already have the "return $promise" statement to end >>>>>> the sub, so it is not the cause. >>>>>> >>>>>> I really suppose the construct will work like the recv function of >>>>>> AnyEvent->condvar. >>>>>> >>>>>> >>>>>> On Wednesday, March 14, 2018 at 9:11:53 PM UTC+8, Andre Parker wrote: >>>>>>> >>>>>>> Hi. >>>>>>> >>>>>>> You should return promise object in get_data sub. Something like: >>>>>>> >>>>>>> my $get_data = sub { >>>>>>> my $promise = Mojo::Promise->new(); >>>>>>> # Some code that resolves promise >>>>>>> ... >>>>>>> return $promise; >>>>>>> }; >>>>>>> >>>>>>> On Wednesday, 14 March 2018 12:18:07 UTC+2, Michael Fung wrote: >>>>>>>> >>>>>>>> Hi all, >>>>>>>> >>>>>>>> I have the following construct using Mojo::Promise: >>>>>>>> >>>>>>>> my $get_data = sub { >>>>>>>> create new Promise object; >>>>>>>> read data from database >>>>>>>> if data read ok { >>>>>>>> $promise->resolve($data); >>>>>>>> } else { >>>>>>>> $promise->reject('no data'); >>>>>>>> } >>>>>>>> }; >>>>>>>> >>>>>>>> >>>>>>>> $get_data->() >>>>>>>> ->then( sub { >>>>>>>> # do something with data >>>>>>>> ... >>>>>>>> }) >>>>>>>> ->catch( sub { >>>>>>>> # log error >>>>>>>> ... >>>>>>>> }) >>>>>>>> ->wait; >>>>>>>> >>>>>>>> say "the end"; >>>>>>>> >>>>>>>> However, I got *"the end*" before running the "do something with >>>>>>>> data" block or catch block. Is there any way to make ->wait really >>>>>>>> wait? >>>>>>>> >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Michael >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>> 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 [email protected]. >>>>>> To post to this group, send email to [email protected]. >>>>>> 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 [email protected]. >>>> To post to this group, send email to [email protected]. >>>> 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 [email protected]. > To post to this group, send email to [email protected]. > 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 [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/mojolicious. For more options, visit https://groups.google.com/d/optout.
