1Mojo::IOLoop::Delay(3)User Contributed Perl DocumentationMojo::IOLoop::Delay(3)
2
3
4

NAME

6       Mojo::IOLoop::Delay - Promises/A+ and flow-control helpers
7

SYNOPSIS

9         use Mojo::IOLoop::Delay;
10
11         # Synchronize multiple non-blocking operations
12         my $delay = Mojo::IOLoop::Delay->new;
13         $delay->steps(sub { say 'BOOM!' });
14         for my $i (1 .. 10) {
15           my $end = $delay->begin;
16           Mojo::IOLoop->timer($i => sub {
17             say 10 - $i;
18             $end->();
19           });
20         }
21         $delay->wait;
22
23         # Sequentialize multiple non-blocking operations
24         Mojo::IOLoop::Delay->new->steps(
25
26           # First step (simple timer)
27           sub ($delay) {
28             Mojo::IOLoop->timer(2 => $delay->begin);
29             say 'Second step in 2 seconds.';
30           },
31
32           # Second step (concurrent timers)
33           sub ($delay, @args) {
34             Mojo::IOLoop->timer(1 => $delay->begin);
35             Mojo::IOLoop->timer(3 => $delay->begin);
36             say 'Third step in 3 seconds.';
37           },
38
39           # Third step (the end)
40           sub ($delay, @args) {
41             say 'And done after 5 seconds total.';
42           }
43         )->wait;
44

DESCRIPTION

46       Mojo::IOLoop::Delay adds flow-control helpers to Mojo::Promise, which
47       can help you avoid deep nested closures that often result from
48       continuation-passing style.
49
50         use Mojo::IOLoop;
51
52         # These deep nested closures are often referred to as "Callback Hell"
53         Mojo::IOLoop->timer(3 => sub ($loop) {
54
55           say '3 seconds';
56           Mojo::IOLoop->timer(3 => sub ($loop) {
57
58             say '6 seconds';
59             Mojo::IOLoop->timer(3 => sub ($loop) {
60
61               say '9 seconds';
62               Mojo::IOLoop->stop;
63             });
64           });
65         });
66
67         Mojo::IOLoop->start;
68
69       The idea behind Mojo::IOLoop::Delay is to turn the nested closures
70       above into a flat series of closures. In the example below, the call to
71       "begin" creates a code reference that we can pass to "timer" in
72       Mojo::IOLoop as a callback, and that leads to the next closure in the
73       series when executed.
74
75         use Mojo::IOLoop;
76
77         # Instead of nested closures we now have a simple chain of steps
78         my $delay = Mojo::IOLoop->delay(
79           sub ($delay) { Mojo::IOLoop->timer(3 => $delay->begin) },
80           sub ($delay) {
81             say '3 seconds';
82             Mojo::IOLoop->timer(3 => $delay->begin);
83           },
84           sub ($delay) {
85             say '6 seconds';
86             Mojo::IOLoop->timer(3 => $delay->begin);
87           },
88           sub ($delay) { say '9 seconds' }
89         );
90         $delay->wait;
91
92       Another positive side effect of this pattern is that we do not need to
93       call "start" in Mojo::IOLoop and "stop" in Mojo::IOLoop manually,
94       because we know exactly when our chain of "steps" has reached the end.
95       So "wait" in Mojo::Promise can stop the event loop automatically if it
96       had to be started at all in the first place.
97

ATTRIBUTES

99       Mojo::IOLoop::Delay inherits all attributes from Mojo::Promise.
100

METHODS

102       Mojo::IOLoop::Delay inherits all methods from Mojo::Promise and
103       implements the following new ones.
104
105   begin
106         my $cb = $delay->begin;
107         my $cb = $delay->begin($offset);
108         my $cb = $delay->begin($offset, $len);
109
110       Indicate an active event by incrementing the event counter, the
111       returned code reference can be used as a callback, and needs to be
112       executed when the event has completed to decrement the event counter
113       again. When all code references generated by this method have been
114       executed and the event counter has reached zero, "steps" will continue.
115
116         # Capture all arguments except for the first one (invocant)
117         my $delay = Mojo::IOLoop->delay(sub ($delay, $err, $stream) { ... });
118         Mojo::IOLoop->client({port => 3000} => $delay->begin);
119         $delay->wait;
120
121       Arguments passed to the returned code reference are spliced with the
122       given offset and length, defaulting to an offset of 1 with no default
123       length. The arguments are then combined in the same order "begin" was
124       called, and passed together to the next step.
125
126         # Capture all arguments
127         my $delay = Mojo::IOLoop->delay(sub ($delay, $loop, $err, $stream) { ... });
128         Mojo::IOLoop->client({port => 3000} => $delay->begin(0));
129         $delay->wait;
130
131         # Capture only the second argument
132         my $delay = Mojo::IOLoop->delay(sub ($delay, $err) { ... });
133         Mojo::IOLoop->client({port => 3000} => $delay->begin(1, 1));
134         $delay->wait;
135
136         # Capture and combine arguments
137         my $delay = Mojo::IOLoop->delay(sub ($delay, $three_err, $three_stream, $four_err, $four_stream) { ... });
138         Mojo::IOLoop->client({port => 3000} => $delay->begin);
139         Mojo::IOLoop->client({port => 4000} => $delay->begin);
140         $delay->wait;
141
142   pass
143         $delay = $delay->pass;
144         $delay = $delay->pass(@args);
145
146       Shortcut for passing values between "steps".
147
148         # Longer version
149         $delay->begin(0)->(@args);
150
151   steps
152         $delay = $delay->steps(sub {...}, sub {...});
153
154       Sequentialize multiple events, every time the event counter reaches
155       zero a callback will run, the first one automatically runs during the
156       next reactor tick unless it is delayed by incrementing the event
157       counter. This chain will continue until there are no remaining
158       callbacks, a callback does not increment the event counter or an
159       exception gets thrown in a callback. Finishing the chain will also
160       result in the promise being fulfilled, or if an exception got thrown it
161       will be rejected.
162

SEE ALSO

164       Mojolicious, Mojolicious::Guides, <https://mojolicious.org>.
165
166
167
168perl v5.32.1                      2021-02-07            Mojo::IOLoop::Delay(3)
Impressum