You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Perl Mojolicious中使用Promise->all_settled时如何限制并发?

在Mojolicious中结合Promise->all_settled实现并发限制的方法

Mojolicious的Mojo::Promise->all_settled本身没有内置并发限制参数,但可以通过Mojo::Promise->map的concurrency选项来实现——先控制任务的并发执行数量,再收集所有任务的结果(无论成功失败),效果等价于带并发限制的all_settled。

核心思路

直接生成50个isOdd_p Promise会同时启动50个子进程,并发过高。我们可以用Promise->map限制同时运行的Promise数量为10,同时为每个Promise添加then/catch包装,把成功/失败的结果转换成统一格式的对象(和all_settled返回的结果结构一致),这样就能既控制并发,又收集所有状态。

修改后的完整代码

use Mojolicious::Lite -signatures, -async_await;

helper isOdd_p => sub($self, $number)
{
    return Mojo::Promise->new(sub($resolve, $reject ) {
        Mojo::IOLoop->subprocess(
            sub {
                sleep 1;
                $number % 2;
            },
            sub ($subprocess, $err, @res ) {
                $reject->( $err ) if $err;
                $reject->( @res ) if @res && $res[0]==0; # 偶数时reject
                $resolve->( @res );
            })
        });
};

any '/' => async sub ($c) {
    $c->render_later();
    
    # 用Promise->map控制并发,并包装结果为all_settled格式
    my @results = await Mojo::Promise->map(
        {concurrency => 10},
        sub {
            my $num = shift;
            return $c->isOdd_p($num)
                ->then(sub { return {status => 'fulfilled', value => shift} })
                ->catch(sub { return {status => 'rejected', reason => shift} });
        },
        0..50
    );
    
    # 注:all_settled永远不会reject,所以原代码里的$@分支永远不会执行
    $c->render(json => [ @results ] );
};

app->start;

关键说明

  1. 并发控制:{concurrency => 10}选项让Promise->map同时最多运行10个Promise,避免一次性启动过多子进程。
  2. 结果格式对齐all_settled:通过then和catch把每个Promise的结果包装成包含status和对应值/原因的对象,和all_settled返回的结果结构完全一致。
  3. 原代码疑问解答:Mojo::Promise->all_settled总是会resolve,不会触发reject,所以原代码里的if (my $err = $@)分支永远不会被执行。

内容的提问来源于stack exchange,提问作者h q

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:48:13