package My::Controller;

sub async {
  my($name, $code) = @_;

  no strict 'refs';
  *$name = sub {
    my @cb = shift->render_later->$code(@_);
    Mojo::IOLoop->delay(@cb) if @cb;
  }
}

sub step (&@) { @_ }

async action_name => sub {
  my $self = shift;

  # ...

  step {
    my($delay) = @_;
    step_one($delay->begin);
  }
  step {
    my($delay, $res) = @_;
    step_two($delay->begin);
  }
  step {
    my($delay, $res) = @_;
    step_three($delay->begin);
  }
};