Async-Chain

 view release on metacpan or  search on metacpan

lib/Async/Chain.pm  view on Meta::CPAN

package Async::Chain;

use 5.006;
use warnings FATAL => 'all';
use overload ('&{}' => \&_to_code, fallback => 1);
use Carp;

=head1 NAME

Async::Chain - The right way to convert nested callback in plain struct
or just the syntax sugar for guy who do not like deep indent.

=head1 VERSION

Version 0.05

=cut

our $VERSION = '0.05';

=head1 SYNOPSIS

Every subroutine in the chain receive callable object as first argument followed
by arguments of object call. You can break chain in every sub, just do not call
C<$next>.

You can skip some subroutins using C<skip> or C<jump> method.

    use Async::Chain;

    # with chain call

    chain
        sub {
            my next = shift;
            AnyEvent::HTTP::http_get('http://perldoc.perl.org/', $next);
        },
        sub {
            my next = shift;
            return $next->jump('log')->(0, "not a 200 response");
            ...
            $db->async_insert(..., cb => $next);
        },
        sub {
            my next = shift;
            ...
            $next->($status, $message);
        },
        log => sub {
            my next = shift;
            my ($status, $message) = @_;
            ...
            log(...);
        };

=head1 RATIONALE

A asynchronous code often have deep nested callbacks, therefore it is tangled
and hard to change. This module help to converta a code like following to some
more readable form. Also, with C<chain> you can easily skip some unneeded steps
in this thread. For example jump to log step after the first failed query in
the chain.

without chain:

    sub f {
        ...
        some_anync_call @args, cb => sub {
            ...
            some_other_anync_call @args, cb => sub {
            ...
                ...
                    ...
                        yet_another_anync_call @args, cb => sub {
                            ...
                        }
            }
        }
    }

using chain:

    chain
        sub {
            my next = shift;
            ...
            some_anync_call @args, cb => sub { $next->(@arg) }
        },
        sub {
            my next = shift;
            ...
            some_other_anync_call @args, cb => sub { $next->(@arg) }
        },
        sub {
            my next = shift;
            ...
        },
        ...
        sub {
            ...
            yet_another_anync_call @args, cb => sub { $next->(@arg) }
        },
        sub {
            ...
        };

If you don't need to skip or hitch links, you can use 'kseq' function from CPS
module, that slightly faster.

=head1 SUBROUTINES/METHODS

=cut

# Internal method called by use function
sub import {
	$caller = (caller())[0];
	*{$caller . "::chain"} = \&chain;
}



( run in 1.074 second using v1.01-cache-2.11-cpan-d8267643d1d )