File Coverage

blib/lib/Promises.pm
Criterion Covered Total %
statement 62 62 100.0
branch 16 20 80.0
condition 8 11 72.7
subroutine 18 18 100.0
pod 5 5 100.0
total 109 116 93.9


line stmt bran cond sub pod time code
1             package Promises;
2             our $AUTHORITY = 'cpan:YANICK';
3             $Promises::VERSION = '1.05';
4             # ABSTRACT: An implementation of Promises in Perl
5              
6 32     32   5242129 use strict;
  32         67  
  32         1434  
7 32     32   1264 use warnings;
  32         217  
  32         2847  
8              
9 32     32   238 use Scalar::Util qw[ blessed ];
  32         67  
  32         3140  
10 32     32   18119 use Promises::Deferred;
  32         93  
  32         3175  
11             our $Backend = 'Promises::Deferred';
12              
13             our $WARN_ON_UNHANDLED_REJECT = 0;
14              
15 32         412 use Sub::Exporter -setup => {
16              
17             collectors => [
18             'backend' => \'_set_backend',
19             'warn_on_unhandled_reject' => \'_set_warn_on_unhandled_reject',
20             ],
21             exports => [qw[
22             deferred resolved rejected
23             collect collect_hash
24             ]]
25 32     32   26159 };
  32         649530  
26              
27             sub _set_warn_on_unhandled_reject {
28 2     2   403 my( undef, $arg ) = @_;
29              
30 2 50       12 if( $WARN_ON_UNHANDLED_REJECT = $arg->[0] ) {
31             # only brings the big guns if asked for
32              
33             *Promises::Deferred::DESTROY = sub {
34              
35 12 50   12   37 return unless $WARN_ON_UNHANDLED_REJECT;
36              
37 12         24 my $self = shift;
38              
39             return unless
40 12 100 100     33 $self->is_rejected and not $self->{_reject_was_handled};
41              
42 4         1975 require Data::Dumper;
43              
44 4         23325 my $dump =
45             Data::Dumper->new([$self->result])->Terse(1)->Dump;
46              
47 4         349 chomp $dump;
48 4         45 $dump =~ s/\n\s*/ /g;
49              
50             warn "Promise's rejection ", $dump,
51             " was not handled",
52 4 100       31 ($self->{_caller} ? ( ' at ', join ' line ', @{$self->{_caller}} ) : ()) , "\n";
  3         38  
53 2         25 };
54             }
55             }
56              
57             sub _set_backend {
58 7     7   1014 my ( undef, $arg ) = @_;
59 7 50       42 my $backend = $arg->[0] or return;
60              
61 7 50       33 unless ( $backend =~ s/^\+// ) {
62 7         24 $backend = 'Promises::Deferred::' . $backend;
63             }
64 7         2770 require Module::Runtime;
65 7   50     16514 $Backend = Module::Runtime::use_module($backend) || return;
66 7         101 return 1;
67              
68             }
69              
70             sub deferred(;&) {
71 105     105 1 7606279 my $promise = $Backend->new;
72              
73 105 100       396 if ( my $code = shift ) {
74 2         9 $promise->resolve;
75             return $promise->then(sub{
76 2     2   6 $code->($promise);
77 2         10 });
78             }
79              
80 103         316 return $promise;
81             }
82              
83 24     24 1 533769 sub resolved { deferred->resolve(@_) }
84 1     1 1 12 sub rejected { deferred->reject(@_) }
85              
86             sub collect_hash {
87             collect(@_)->then( sub {
88             map {
89 5     5   14 my @values = @$_;
  22         51  
90 22 100       48 die "'collect_hash' promise returned more than one value: [@{[ join ', ', @values ]} ]\n"
  1         15  
91             if @values > 1;
92              
93 21 100       67 @values == 1 ? $values[0] : undef;
94             } @_ })
95 7     7 1 33 }
96              
97             sub collect {
98 18     18 1 1319 my @promises = @_;
99              
100 18         52 my $all_done = resolved();
101              
102 18         30 my @results;
103 18         42 for my $p ( @promises ) {
104 48 100 66     329 if ( $p && blessed $p && $p->can('then') ) {
      66        
105             $all_done = $all_done->then( sub {
106             $p->then( sub {
107 18         58 push @results, [ @_ ];
108 18         64 return;
109             } )
110 24     22   128 } );
  22         119  
111             } else {
112             # not actually a promise; collect directly
113             $all_done = $all_done->then( sub {
114 23     23   62 push @results, [ $p ];
115 23         50 return;
116 24         161 } );
117             }
118             }
119              
120 18     14   79 return $all_done->then( sub { @results } );
  14         44  
121             }
122              
123             1;
124              
125             __END__