第一次招贴画,温柔点。
我想要类似于Mojo::诺言->all的东西,除了有一个选项放弃某些被拒绝的(或者,我猜是已解决的)承诺依赖于拒绝值,这是由调用者决定的。
只在内部使用这个,所以不用担心我污染了Mojo::诺言::命名空间。
package Mojo::Promise::Filter;
use Moose;
extends 'Mojo::Promise';
has 'promises' => (
isa => 'ArrayRef[Mojo::Promise]',
is => 'ro',
required => 1,
);
has 'resolve_filter' => ( # truthy return means *DO* filter out
isa => 'CodeRef',
is => 'ro',
required => 1,
lazy => 1,
default => sub { return sub {}; },
);
has 'reject_filter' => ( # truthy return means *DO* filter out
isa => 'CodeRef',
is => 'ro',
required => 1,
lazy => 1,
default => sub { return sub {}; },
);
has '_promises_state_tracker' => (
# numbered hashref whose primary keys correspond to passed promise-array's indices
# secondary keys are flags for whether each original promise filtered
# and whether promise resolved/rejected,
# plus the original promise itself, e.g. :
# { 0 => { filtered => (undef|1), ror => (undef|1), original_promise => (Mojo::Promise) } }
isa => 'HashRef[HashRef]',
is => 'ro',
lazy => 1,
builder => '_build_promises_state_tracker',
);
sub _build_promises_state_tracker {
my $self = shift;
my $i = 0;
return { map { $i++ => { original_promise => $_ } } @{$self->promises} };
}
sub _resolve_or_reject_self_if_last_child {
my $self = shift;
my @ror = grep { $_->{ror} } values %{$self->_promises_state_tracker};
# gather the thus-far resolved-or-rejected promises
return unless scalar keys %{$self->_promises_state_tracker} == scalar @ror;
# return unless we have as many ror promises as were passed in
my @unfiltered = map { $_->{original_promise} } grep { !$_->{filtered} } values %{$self->_promises_state_tracker};
return Mojo::Promise->all(@unfiltered)->then(sub {
$self->resolve(@_)
})->catch(sub {
$self->reject(@_)
});
}
sub filter {
my $self = shift;
for my $i (0 .. $#{$self->promises}) {
$self->promises->[$i]->then(sub {
$self->_promises_state_tracker->{$i}->{filtered} = 1
if $self->resolve_filter->(@_);
})->catch(sub {
$self->_promises_state_tracker->{$i}->{filtered} = 1
if $self->reject_filter->(@_);
})->finally(sub {
$self->_promises_state_tracker->{$i}->{ror} = 1;
# ror = Resolved Or Rejected
$self->_resolve_or_reject_self_if_last_child();
});
}
return $self;
}
no Moose;
1;用作:
my $re_filter = qr/some special text/;
my $reject_filter = sub {
my $v = shift;
return 1 if ref \$v eq 'SCALAR' && $v =~ $re_filter;
};
my $p = Mojo::Promise::Filter->new(
reject_filter => $reject_filter,
promises => \@promises
);
return $p->filter;发布于 2018-09-08 19:04:19
莫灼里已经有角色了。
package Mojo::Promise::Role::Filter {
use Mojo::Base '-role';
...; # stuff you want in the Promise class
}
my $promise->with_roles( '+Filter' )->new;
...;参见,例如,莫霍::承诺::角色::任何。
https://codereview.stackexchange.com/questions/195959
复制相似问题