1Mojo::Promise(3) User Contributed Perl Documentation Mojo::Promise(3)
2
3
4
6 Mojo::Promise - Promises/A+
7
9 use Mojo::Promise;
10 use Mojo::UserAgent;
11
12 # Wrap continuation-passing style APIs with promises
13 my $ua = Mojo::UserAgent->new;
14 sub get_p {
15 my $promise = Mojo::Promise->new;
16 $ua->get(@_ => sub ($ua, $tx) {
17 my $err = $tx->error;
18 if (!$err || $err->{code}) { $promise->resolve($tx) }
19 else { $promise->reject($err->{message}) }
20 });
21 return $promise;
22 }
23
24 # Perform non-blocking operations sequentially
25 get_p('https://mojolicious.org')->then(sub ($mojo) {
26 say $mojo->res->code;
27 return get_p('https://metacpan.org');
28 })->then(sub ($cpan) {
29 say $cpan->res->code;
30 })->catch(sub ($err) {
31 warn "Something went wrong: $err";
32 })->wait;
33
34 # Synchronize non-blocking operations (all)
35 my $mojo = get_p('https://mojolicious.org');
36 my $cpan = get_p('https://metacpan.org');
37 Mojo::Promise->all($mojo, $cpan)->then(sub ($mojo, $cpan) {
38 say $mojo->[0]->res->code;
39 say $cpan->[0]->res->code;
40 })->catch(sub ($err) {
41 warn "Something went wrong: $err";
42 })->wait;
43
44 # Synchronize non-blocking operations (race)
45 my $mojo = get_p('https://mojolicious.org');
46 my $cpan = get_p('https://metacpan.org');
47 Mojo::Promise->race($mojo, $cpan)->then(sub ($tx) {
48 say $tx->req->url, ' won!';
49 })->catch(sub ($err) {
50 warn "Something went wrong: $err";
51 })->wait;
52
54 Mojo::Promise is a Perl-ish implementation of Promises/A+
55 <https://promisesaplus.com> and a superset of ES6 Promises
56 <https://duckduckgo.com/?q=n%20Promise>.
57
59 A promise is an object representing the eventual completion or failure
60 of a non-blocking operation. It allows non-blocking functions to return
61 values, like blocking functions. But instead of immediately returning
62 the final value, the non-blocking function returns a promise to supply
63 the value at some point in the future.
64
65 A promise can be in one of three states:
66
67 pending
68 Initial state, neither fulfilled nor rejected.
69
70 fulfilled
71 Meaning that the operation completed successfully.
72
73 rejected
74 Meaning that the operation failed.
75
76 A pending promise can either be fulfilled with a value or rejected with
77 a reason. When either happens, the associated handlers queued up by a
78 promise's "then" method are called.
79
81 Mojo::Promise implements the following attributes.
82
83 ioloop
84 my $loop = $promise->ioloop;
85 $promise = $promise->ioloop(Mojo::IOLoop->new);
86
87 Event loop object to control, defaults to the global Mojo::IOLoop
88 singleton. Note that this attribute is weakened.
89
91 Mojo::Promise inherits all methods from Mojo::Base and implements the
92 following new ones.
93
94 all
95 my $new = Mojo::Promise->all(@promises);
96
97 Returns a new Mojo::Promise object that either fulfills when all of the
98 passed Mojo::Promise objects have fulfilled or rejects as soon as one
99 of them rejects. If the returned promise fulfills, it is fulfilled with
100 the values from the fulfilled promises in the same order as the passed
101 promises.
102
103 all_settled
104 my $new = Mojo::Promise->all_settled(@promises);
105
106 Returns a new Mojo::Promise object that fulfills when all of the passed
107 Mojo::Promise objects have fulfilled or rejected, with hash references
108 that describe the outcome of each promise.
109
110 any
111 my $new = Mojo::Promise->any(@promises);
112
113 Returns a new Mojo::Promise object that fulfills as soon as one of the
114 passed Mojo::Promise objects fulfills, with the value from that
115 promise.
116
117 catch
118 my $new = $promise->catch(sub {...});
119
120 Appends a rejection handler callback to the promise, and returns a new
121 Mojo::Promise object resolving to the return value of the callback if
122 it is called, or to its original fulfillment value if the promise is
123 instead fulfilled.
124
125 # Longer version
126 my $new = $promise->then(undef, sub {...});
127
128 # Pass along the rejection reason
129 $promise->catch(sub (@reason) {
130 warn "Something went wrong: $reason[0]";
131 return @reason;
132 });
133
134 # Change the rejection reason
135 $promise->catch(sub (@reason) { "This is bad: $reason[0]" });
136
137 clone
138 my $new = $promise->clone;
139
140 Return a new Mojo::Promise object cloned from this promise that is
141 still pending.
142
143 finally
144 my $new = $promise->finally(sub {...});
145
146 Appends a fulfillment and rejection handler to the promise, and returns
147 a new Mojo::Promise object resolving to the original fulfillment value
148 or rejection reason.
149
150 # Do something on fulfillment and rejection
151 $promise->finally(sub { say "We are done!" });
152
153 map
154 my $new = Mojo::Promise->map(sub {...}, @items);
155 my $new = Mojo::Promise->map({concurrency => 3}, sub {...}, @items);
156
157 Apply a function that returns a Mojo::Promise to each item in a list of
158 items while optionally limiting concurrency. Returns a Mojo::Promise
159 that collects the results in the same manner as "all". If any item's
160 promise is rejected, any remaining items which have not yet been mapped
161 will not be.
162
163 # Perform 3 requests at a time concurrently
164 Mojo::Promise->map({concurrency => 3}, sub { $ua->get_p($_) }, @urls)
165 ->then(sub{ say $_->[0]->res->dom->at('title')->text for @_ });
166
167 These options are currently available:
168
169 concurrency
170 concurrency => 3
171
172 The maximum number of items that are in progress at the same time.
173
174 new
175 my $promise = Mojo::Promise->new;
176 my $promise = Mojo::Promise->new(sub {...});
177
178 Construct a new Mojo::Promise object.
179
180 # Wrap a continuation-passing style API
181 my $promise = Mojo::Promise->new(sub ($resolve, $reject) {
182 Mojo::IOLoop->timer(5 => sub {
183 if (int rand 2) { $resolve->('Lucky!') }
184 else { $reject->('Unlucky!') }
185 });
186 });
187
188 race
189 my $new = Mojo::Promise->race(@promises);
190
191 Returns a new Mojo::Promise object that fulfills or rejects as soon as
192 one of the passed Mojo::Promise objects fulfills or rejects, with the
193 value or reason from that promise.
194
195 reject
196 my $new = Mojo::Promise->reject(@reason);
197 $promise = $promise->reject(@reason);
198
199 Build rejected Mojo::Promise object or reject the promise with one or
200 more rejection reasons.
201
202 # Longer version
203 my $promise = Mojo::Promise->new->reject(@reason);
204
205 resolve
206 my $new = Mojo::Promise->resolve(@value);
207 $promise = $promise->resolve(@value);
208
209 Build resolved Mojo::Promise object or resolve the promise with one or
210 more fulfillment values.
211
212 # Longer version
213 my $promise = Mojo::Promise->new->resolve(@value);
214
215 then
216 my $new = $promise->then(sub {...});
217 my $new = $promise->then(sub {...}, sub {...});
218 my $new = $promise->then(undef, sub {...});
219
220 Appends fulfillment and rejection handlers to the promise, and returns
221 a new Mojo::Promise object resolving to the return value of the called
222 handler.
223
224 # Pass along the fulfillment value or rejection reason
225 $promise->then(
226 sub (@value) {
227 say "The result is $value[0]";
228 return @value;
229 },
230 sub (@reason) {
231 warn "Something went wrong: $reason[0]";
232 return @reason;
233 }
234 );
235
236 # Change the fulfillment value or rejection reason
237 $promise->then(
238 sub (@value) { return "This is good: $value[0]" },
239 sub (@reason) { return "This is bad: $reason[0]" }
240 );
241
242 timer
243 my $new = Mojo::Promise->timer(5 => 'Success!');
244 $promise = $promise->timer(5 => 'Success!');
245 $promise = $promise->timer(5);
246
247 Create a new Mojo::Promise object with a timer or attach a timer to an
248 existing promise. The promise will be resolved after the given amount
249 of time in seconds with or without a value.
250
251 timeout
252 my $new = Mojo::Promise->timeout(5 => 'Timeout!');
253 $promise = $promise->timeout(5 => 'Timeout!');
254 $promise = $promise->timeout(5);
255
256 Create a new Mojo::Promise object with a timeout or attach a timeout to
257 an existing promise. The promise will be rejected after the given
258 amount of time in seconds with a reason, which defaults to "Promise
259 timeout".
260
261 wait
262 $promise->wait;
263
264 Start "ioloop" and stop it again once the promise has been fulfilled or
265 rejected, does nothing when "ioloop" is already running.
266
268 You can set the "MOJO_PROMISE_DEBUG" environment variable to get some
269 advanced diagnostics information printed to "STDERR".
270
271 MOJO_PROMISE_DEBUG=1
272
274 Mojolicious, Mojolicious::Guides, <https://mojolicious.org>.
275
276
277
278perl v5.38.0 2023-09-11 Mojo::Promise(3)