++ed by:
Author image 💯 Doug Bell
and 3 contributors


Beam::Emitter::Cookbook - Recipes for simple Beam::Emitter patterns


version 1.007


This document contains recipes for things that Beam::Emitter does not do by default, but that you can add to your project with only a few lines of code.


Allow a single listener to catch all events

Sometimes you might want to be able to listen for every single event that comes from an event emitter. To do this, we can create an extension of the Beam::Emitter that also forwards the event on to a special event called *:

    package My::Emitter;
    use Moo;
    with 'Beam::Emitter';
    after emit => sub {
        my ( $self, $event_name, @args ) = @_;
        return if $event_name eq '*';
        $self->emit( '*', name => $event_name, @args );

Because we pass in the name key to emit(), the original name of the event will be available to our listener as $event->name.

Use an object method as an event handler

Often you might want to use an object method as an event handler so that your event handler has access to your object's data and methods. You could manually create a subroutine that calls your method, like so:

    $emitter->on( 'event', sub { $object->method( @_ ) } );

But this has a couple drawbacks: It's a bunch of typing, and it closes over a reference to your object which means your object lives as long as the event emitter does. This can even cause circular references, which are a common cause of memory problems in Perl.

To fix these problems, you could again do it manually:

    use Scalar::Util qw( weaken );
    weaken $object; # Reduce our object's reference count
    $emitter->on( 'event', sub {
        return unless $object; # We might have been cleaned up
        $object->method( @_ );
    } );

Or you could use the curry module:

    $emitter->on( 'event', $object->curry::weak::method );

The "curry" module creates new subroutine references from existing ones, passing in any arguments. There's a corresponding "curry::weak" module which does the same thing, but weakens any references used as arguments. This is the easiest way to use object methods as event handlers.

Add custom data to an event handler

To add additional data to an event handler when it's created, you can simply "close over" the variable in your new subroutine, like so:

    my $name = "Doug";
    $emitter->on( introduce => sub {
        print "Hello, my name is $name";
    } );


Doug Bell <preaction@cpan.org>


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.