AnyEvent-Promises

 view release on metacpan or  search on metacpan

lib/AnyEvent/Promises.pm  view on Meta::CPAN

sub make_promise {
    my $arg = shift;

    return $arg if is_promise($arg);

    my $d = deferred();
    if ( ref $arg && ref $arg eq 'CODE' ) {
        $d->resolve;
        return $d->promise->then($arg);
    }
    else {
        $d->resolve($arg);
        return $d->promise;
    }
}

sub merge_promises {
    my @promises = @_;

    my $d    = deferred();
    my $left = @promises;
    my @result;
    for my $i ( 0 .. $#promises ) {
        $promises[$i]->then(
            sub {
                # only the first value is taken into consideration
                $result[$i] = $_[0];
                --$left or $d->resolve(@result);
            },
            sub {
                $d->reject(@_);
            }
        );
    }
    if (!$left){
        # is true only when @promises is empty
        $d->resolve;
    }
    return $d->promise;
}

# actually is_thenable
sub is_promise {
    my ($cand) = @_;
    return blessed($cand) && $cand->can('then');
}

sub settle_promises {
    my @promises = shift;

    my $d    = deferred();
    my $left = @promises;

    my $cb = sub { --$left or $d->resolve(@promises); };
    $_->then( $cb, $cb ) for @promises;
    return $d->promise;
}

1;
    
# vim: expandtab:shiftwidth=4:tabstop=4:softtabstop=0:textwidth=78:

__END__

=pod

=head1 NAME

AnyEvent::Promises - simple implementation of Promises/A+ spec

=head1 VERSION

version 0.06

=head1 SYNOPSIS

    use AnyEvent::Promises qw(deferred merge_promises);
    use AnyEvent::HTTP;
    use JSON qw(decode_json encode_json);

    sub wget {
        my ($uri) = @_;
        my $d = deferred;
        http_get $uri => sub {
            my ( $body, $headers ) = @_;
            $headers->{Status} == 200
                ? $d->resolve( decode_json($body) )
                : $d->reject('receiving data failed with status: '.  $headers->{Status} );
        };
        return $d->promise;
    }

    sub wput {
        my ($uri, $data) = @_;
        my $d = deferred;

        http_put $uri, body => encode_json($data) => sub {
            my ( $body, $headers ) = @_;
            $headers->{Status} == 200 || $headers->{Status} == 204
                ? $d->resolve( $body? decode_json($body) )
                : $d->reject('putting data failed with status: '.  $headers->{Status} );
        };
        return $d->promise;
    }

    my $cv = AnyEvent->condvar;
    merge_promises(
        wget('http://rest.api.example.com/customer/12345'),
        wget('http://rest.api.example.com/order/2345'),
        wget('http://rest.api.example.com/payment/3456')
    )->then(
        sub {
            my ($customer, $order, $payment) = @_;

            my $data = mix_together($customer, $order, $payment);
            return wput('http://rest2.api.example.com/aggregate/567', $data);
        }
    )->then(
        sub {
            # do something after the data are send
        },



( run in 1.372 second using v1.01-cache-2.11-cpan-97f6503c9c8 )