Beam-Emitter
view release on metacpan or search on metacpan
lib/Beam/Emitter.pm view on Meta::CPAN
#pod extends 'Beam::Event';
#pod
#pod has who => (
#pod is => 'ro',
#pod required => 1,
#pod );
#pod
#pod Now that we can represent who is knocking, let's notify our subscribers.
#pod
#pod package Door;
#pod use Moo;
#pod use Door::Knock; # Our emitter must load the class, Beam::Emitter will not
#pod with 'Beam::Emitter';
#pod
#pod sub open {
#pod my ( $self, $who ) = @_;
#pod my $event = $self->emit( 'before_open', class => 'Door::Knock', who => $who );
#pod return if $event->is_default_stopped;
#pod $self->open_the_door;
#pod }
#pod
#pod Finally, let's build a listener that knows who is allowed in the door.
#pod
#pod my $private_door = Door->new;
#pod $private_door->on( before_open => sub {
#pod my ( $event ) = @_;
#pod
#pod if ( $event->who ne 'preaction' ) {
#pod $event->stop_default;
#pod }
#pod
#pod } );
#pod
#pod $private_door->open;
#pod
#pod =head2 Without Beam::Event
#pod
#pod Although checking C<is_default_stopped> is completely optional, if you do not
#pod wish to use the C<Beam::Event> object, you can instead call L<emit_args>
#pod instead of L<emit> to give arbitrary arguments to your listeners.
#pod
#pod package Door;
#pod use Moo;
#pod with 'Beam::Emitter';
#pod
#pod sub open {
#pod my ( $self, $who ) = @_;
#pod $self->emit_args( 'open', $who );
#pod $self->open_the_door;
#pod }
#pod
#pod There's no way to stop the door being opened, but you can at least notify
#pod someone before it does.
#pod
#pod =head1 SEE ALSO
#pod
#pod =over 4
#pod
#pod =item L<Beam::Event>
#pod
#pod =item L<Beam::Emitter::Cookbook>
#pod
#pod This document contains some useful patterns for your event emitters and
#pod listeners.
#pod
#pod =item L<http://perladvent.org/2013/2013-12-16.html>
#pod
#pod Coordinating Christmas Dinner with Beam::Emitter by Yanick Champoux.
#pod
#pod =back
#pod
#pod =cut
use strict;
use warnings;
use Types::Standard qw(:all);
use Scalar::Util qw( weaken refaddr );
use Carp qw( croak );
use Beam::Event;
use Module::Runtime qw( use_module );
use Moo::Role; # Put this last to ensure proper, automatic cleanup
# The event listeners on this object, a hashref of arrayrefs of
# EVENT_NAME => [ Beam::Listener object, ... ]
has _listeners => (
is => 'ro',
isa => HashRef,
default => sub { {} },
);
#pod =method subscribe ( event_name, subref, [ %args ] )
#pod
#pod Subscribe to an event from this object. C<event_name> is the name of the event.
#pod C<subref> is a subroutine reference that will get either a L<Beam::Event> object
#pod (if using the L<emit> method) or something else (if using the L<emit_args> method).
#pod
#pod Returns a coderef that, when called, unsubscribes the new subscriber.
#pod
#pod my $unsubscribe = $emitter->subscribe( open_door => sub {
#pod warn "ding!";
#pod } );
#pod $emitter->emit( 'open_door' ); # ding!
#pod $unsubscribe->();
#pod $emitter->emit( 'open_door' ); # no ding
#pod
#pod This unsubscribe subref makes it easier to stop our subscription in a safe,
#pod non-leaking way:
#pod
#pod my $unsub;
#pod $unsub = $emitter->subscribe( open_door => sub {
#pod $unsub->(); # Only handle one event
#pod } );
#pod $emitter->emit( 'open_door' );
#pod
#pod The above code does not leak memory, but the following code does:
#pod
#pod # Create a memory cycle which must be broken manually
#pod my $cb;
lib/Beam/Emitter.pm view on Meta::CPAN
# add metadata with subscription time
has sub_time => is ( 'ro',
init_arg => undef,
default => sub { time() },
);
}
# My::Emitter consumes the Beam::Emitter role
my $emitter = My::Emitter->new;
$emitter->on( "foo",
sub { print "Foo happened!\n"; },
class => MyListener
);
The L</listeners> method can be used to examine the subscribed listeners.
=head2 on ( event_name, subref )
An alias for L</subscribe>. B<NOTE>: Do not use this alias for method
modifiers! If you want to override behavior, override C<subscribe>.
=head2 unsubscribe ( event_name [, subref ] )
Unsubscribe from an event. C<event_name> is the name of the event. C<subref> is
the single listener subref to be removed. If no subref is given, will remove
all listeners for this event.
=head2 un ( event_name [, subref ] )
An alias for L</unsubscribe>. B<NOTE>: Do not use this alias for method
modifiers! If you want to override behavior, override C<unsubscribe>.
=head2 emit ( name, event_args )
Emit a L<Beam::Event> with the given C<name>. C<event_args> is a list of name => value
pairs to give to the C<Beam::Event> constructor.
Use the C<class> key in C<event_args> to specify a different Event class.
=head2 emit_args ( name, callback_args )
Emit an event with the given C<name>. C<callback_args> is a list that will be given
directly to each subscribed callback.
Use this if you want to avoid using L<Beam::Event>, though you miss out on the control
features like L<stop|Beam::Event/stop> and L<stop default|Beam::Event/stop_default>.
=head2 listeners ( event_name )
Returns a list containing the listeners which have subscribed to the
specified event from this emitter. The list elements are either
instances of L<Beam::Listener> or of custom classes specified in calls
to L</subscribe>.
=head1 SEE ALSO
=over 4
=item L<Beam::Event>
=item L<Beam::Emitter::Cookbook>
This document contains some useful patterns for your event emitters and
listeners.
=item L<http://perladvent.org/2013/2013-12-16.html>
Coordinating Christmas Dinner with Beam::Emitter by Yanick Champoux.
=back
=head1 AUTHOR
Doug Bell <preaction@cpan.org>
=head1 CONTRIBUTORS
=for stopwords Diab Jerius Joel Berger Yanick Champoux
=over 4
=item *
Diab Jerius <djerius@cfa.harvard.edu>
=item *
Joel Berger <joel.a.berger@gmail.com>
=item *
Yanick Champoux <yanick@babyl.dyndns.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2016 by Doug Bell.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
( run in 1.499 second using v1.01-cache-2.11-cpan-39bf76dae61 )