1Promises::Cookbook::TIMUTsOeWrTDCIo(n3t)ributed Perl DocPurmoemnitsaetsi:o:nCookbook::TIMTOWTDI(3)
2
3
4

NAME

6       Promises::Cookbook::TIMTOWTDI - Counter examples to Promises
7

VERSION

9       version 1.04
10

DESCRIPTION

12       So, like I said before, Promises are a means by which you can more
13       effectively manage your async operations and avoid callback spaghetti.
14       But of course this is Perl and therefore there is always another way to
15       do it. In this section I am going to show a few examples of other ways
16       you could accomplish the same thing.
17
18   Caveat
19       Please note that I am specifically illustrating ways to do this which I
20       feel are inferior or less elegant then Promises. This is not meant to
21       be a slight on the API of other modules at all, I am simply using these
22       modules to try and illustrate other (perhaps more familiar) idioms in
23       hopes that it will help people understand Promises.
24
25       I am sure there are other ways to do some of these things and do them
26       more effectively, and I am fully willing to admit my ignorance here. I
27       welcome any patches which might illustrate said ignorance, as I do not
28       claim at all to be an expert in async programming.
29

AnyEvent::HTTP

31       So, enough caveating, please consider this (more traditional) version
32       of our the Promises SYNOPSIS example using AnyEvent::HTTP.
33
34         my $cv = AnyEvent->condvar;
35
36         http_get('http://rest.api.example.com/-/product/12345', sub {
37             my ($product) = @_;
38             http_get('http://rest.api.example.com/-/product/suggestions?for_sku=12345', sub {
39                 my ($suggestions) = @_;
40                 http_get('http://rest.api.example.com/-/product/reviews?for_sku=12345', sub {
41                     my ($reviews) = @_;
42                     $cv->send({
43                         product     => $product,
44                         suggestions => $suggestions,
45                         reviews     => $reviews,
46                     })
47                 }),
48             });
49         });
50
51         my $all_product_info = $cv->recv;
52
53       Not only do we have deeply nested callbacks, but we have an enforced
54       order of operations. If you wanted to try and avoid that order of
55       operations, you might end up writing something like this:
56
57          my $product_cv    = AnyEvent->condvar;
58          my $suggestion_cv = AnyEvent->condvar;
59          my $review_cv     = AnyEvent->condvar;
60
61          http_get('http://rest.api.example.com/-/product/12345', sub {
62              my ($product) = @_;
63              $product_cv->send( $product );
64          });
65
66          http_get('http://rest.api.example.com/-/product/suggestions?for_sku=12345', sub {
67              my ($suggestions) = @_;
68              $suggestion_cv->send( $suggestions );
69          });
70
71          http_get('http://rest.api.example.com/-/product/reviews?for_sku=12345', sub {
72              my ($reviews) = @_;
73              $reviews_cv->send( $reviews )
74          }),
75
76          my $all_product_info = {
77              product     => $product_cv->recv,
78              suggestions => $suggestions_cv->recv,
79              reviews     => $reviews_cv->recv
80          };
81
82       But actually, this doesn't work either, while we do gain something by
83       allowing the "http_get" calls to be run in whatever order works best,
84       we still end up still enforcing some order in the way we call "recv" on
85       our three "condvars" (Oh yeah, and we had to create and manage three
86       "condvars" as well).
87
88       The following example was submitted to me by James Wright (via RT
89       #83992) as an alternate approach which is non-nested, uses only one
90       condvar, and has no fixed-order.
91
92         my $cv = AnyEvent->condvar;
93         my ( $product, $suggestions, $reviews ) = ( [], [], [] );
94
95         $cv->begin;
96         http_get('http://rest.api.example.com/-/product/12345', sub {
97             ($product) = @_;
98             $cv->end;
99         });
100
101         $cv->begin;
102         http_get('http://rest.api.example.com/-/product/suggestions?for_sku=12345', sub {
103             ($suggestions) = @_;
104             $cv->end;
105         });
106
107         $cv->begin;
108         http_get('http://rest.api.example.com/-/product/reviews?for_sku=12345', sub {
109             ($reviews) = @_;
110             $cv->end;
111         });
112
113         $cv->cb(sub {
114             $cv->send({
115                 product     => $product,
116                 suggestions => $suggestions,
117                 reviews     => $reviews,
118             });
119         });
120
121         my $all_product_info = $cv->recv;
122
123       The only real issue I have with this approach is the semi-global
124       variable usage ($product, $suggestions and $reviews), but otherwise it
125       works fine.
126
127       NOTE: Again, if you can think of a better way to do this that I missed,
128       please let me know.
129

Mojo::UserAgent

131           #!/usr/bin/env perl
132
133           use Mojo::Base -strict;
134           use Mojo::UserAgent;
135
136           my $titles;
137
138           my $ua = Mojo::UserAgent->new;
139           Mojo::IOLoop->delay(
140               sub {
141                   my $delay = shift;
142                   $ua->get('http://google.com/', $delay->begin);
143                   $ua->get('http://yahoo.com/', $delay->begin);
144                   $ua->get('http://perlmonks.org/', $delay->begin);
145               },
146               sub {
147                   my ($delay, $tx1, $tx2, $tx3) = @_;
148                   $titles = {
149                       google      => $tx1->res->dom->at('title')->text,
150                       yahoo       => $tx2->res->dom->at('title')->text,
151                       perlmonks   => $tx3->res->dom->at('title')->text,
152                   };
153               },
154           )->catch(
155               sub {
156                   my ($delay, $err) = @_;
157                   warn "failed to download or parse title\n";
158               }
159           )->wait;
160
161           say Mojo::Util::dumper($titles);
162

AUTHOR

164       Stevan Little <stevan.little@iinteractive.com>
165
167       This software is copyright (c) 2020, 2019, 2017, 2014, 2012 by Infinity
168       Interactive, Inc.
169
170       This is free software; you can redistribute it and/or modify it under
171       the same terms as the Perl 5 programming language system itself.
172
173
174
175perl v5.32.1                      2021-01-27  Promises::Cookbook::TIMTOWTDI(3)
Impressum