File Coverage

blib/lib/Mojo/Promise/Role/Some.pm
Criterion Covered Total %
statement 21 21 100.0
branch 10 10 100.0
condition n/a
subroutine 5 5 100.0
pod 1 1 100.0
total 37 37 100.0


line stmt bran cond sub pod time code
1             package Mojo::Promise::Role::Some;
2 1     1   709 use Mojo::Base '-role';
  1         3  
  1         7  
3              
4 1     1   401 use strict;
  1         2  
  1         280  
5              
6             our $VERSION = '1.003';
7              
8             =encoding utf8
9              
10             =head1 NAME
11              
12             Mojo::Promise::Role::Some - Fulfill when a certain number of promises are fulfilled
13              
14             =head1 SYNOPSIS
15              
16             use Mojo::Promise;
17             use Mojo::Util qw(dumper);
18              
19             my @promises = map { Mojo::Promise->new } 0 .. 5;
20             my $some_promise = Mojo::Promise
21             ->with_roles( '+Some' )
22             ->some( \@promises, $count_to_fulfill );
23              
24             $some_promise->then(
25             sub { say dumper( @_ ) }
26             sub { say "Failed!" }
27             );
28              
29             $some_promise->wait;
30              
31             =head1 DESCRIPTION
32              
33             Make a new promise that fulfills with a certain number of its promises
34             fulfill. Fire off several tasks and fulfill when a minimum number of them
35             work out.
36              
37             This should be the Perl expression of the same idea in
38             bluebirdjs (L).
39              
40             =over 4
41              
42             =item some( \@promises, $count )
43              
44             Takes a lists of promises (or thenables) and returns another promise
45             that fulfills when C<$count> promises fulfill. The result is list of
46             array references for the arguments for the fulfilled promises in the
47             order that they were fulfilled.
48              
49             If less than C<$count> promises fulfill then the some promise rejects.
50             The result is list of array references for the arguments for the
51             rejected promises in the order that they were rejected. The number of elements
52             in that list should be the PROMISES - COUNT + 1 since the extra reject
53             is the response that makes it impossible to get to COUNT fulfills.
54              
55             If you pass no promises, the some promise fulfills if you specify
56             C<$count = 0> and rejects otherwise.
57              
58             =cut
59              
60             sub some {
61 9     9 1 35354 my( $self, $promises, $n ) = @_;
62 9         30 my $some = $self->new;
63              
64 9 100       256 return $n == 0 ? $some->resolve : $some->reject if @$promises == 0;
    100          
65 4 100       13 return $some->reject if $n > @$promises;
66              
67 3         6 my $remaining = @$promises;
68              
69 3         4 my( @resolved, @rejected );
70 3         6 foreach my $p ( @$promises ) {
71             $p->then(
72             sub {
73 9     9   1726 $remaining--;
74 9         18 push @resolved, [ @_ ];
75 9 100       26 $some->resolve( @resolved ) if @resolved == $n;
76             },
77             sub {
78             # I keep trying to come up with a situation where
79             # you'd reject $some with fewer rejections, but as
80             # long as the sum of the pending and fulfilled is at
81             # least the minimum count, there's always a chance.
82             # The only way for that to not be true is for there
83             # to be enough rejections to make pending small enough.
84             # That's PROMISES - N + 1. Let's see if I can understand
85             # that the next time I come through this. I still don't
86             # believe it.
87 10     10   3190 $remaining--;
88 10         23 push @rejected, [ @_ ];
89 10 100       49 $some->reject( @rejected ) if @rejected > @$promises - $n
90             },
91             )
92 19         683 }
93              
94 3         115 return $some;
95             }
96              
97             =back
98              
99             =head1 SEE ALSO
100              
101             L, L, L
102              
103             L
104              
105             =head1 SOURCE AVAILABILITY
106              
107             This source is in Github:
108              
109             https://github.com/briandfoy/mojo-promise-role-higherorder
110              
111             =head1 AUTHOR
112              
113             brian d foy, C<< >>
114              
115             =head1 COPYRIGHT AND LICENSE
116              
117             Copyright © 2018-2021, brian d foy, All Rights Reserved.
118              
119             You may redistribute this under the terms of the Artistic License 2.0.
120              
121             =cut
122              
123             1;