首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >扩展Mojo::承诺

扩展Mojo::承诺
EN

Code Review用户
提问于 2018-06-06 14:00:17
回答 1查看 260关注 0票数 7

第一次招贴画,温柔点。

我想要类似于Mojo::诺言->all的东西,除了有一个选项放弃某些被拒绝的(或者,我猜是已解决的)承诺依赖于拒绝值,这是由调用者决定的。

只在内部使用这个,所以不用担心我污染了Mojo::诺言::命名空间。

代码语言:javascript
复制
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;

用作:

代码语言:javascript
复制
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;
EN

回答 1

Code Review用户

发布于 2018-09-08 19:04:19

莫灼里已经有角色了。

代码语言:javascript
复制
 package Mojo::Promise::Role::Filter {
     use Mojo::Base '-role';
     ...; # stuff you want in the Promise class
     }

 my $promise->with_roles( '+Filter' )->new;
 ...;

参见,例如,莫霍::承诺::角色::任何

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/195959

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档