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

Dancer2中GET请求调用方法时出现无限循环问题求助

解决Dancer2迁移后的拍照亭无限循环问题

我来帮你梳理下这个问题的核心原因,并且给出几个比全局变量更优雅的解决方案:

问题根源分析

你遇到的无限循环,本质是耗时的拍照操作导致请求响应延迟,浏览器触发重试机制,重复调用/photo路由,加上原代码可能没有有效的防重复触发逻辑,最终导致相机不断拍照、页面持续刷新。Dancer2和Dancer1在请求处理的超时控制、异步支持上有差异,这也是迁移后问题暴露的原因。

解决方案

1. 用Dancer2的异步响应处理耗时操作

Dancer2原生支持异步请求处理,通过delayed关键字可以把耗时的拍照逻辑放到后台执行,避免请求超时导致浏览器重试:

package App;
use Dancer2;
use Photobox;

my $photobox = Photobox->new();  # 这里注意类名要符合Perl驼峰式规范

get '/photo' => sub {
    my $response = delayed {
        my $photo = $photobox->takePicture();
        # 确保redirect_uri指向/showphoto,而非/photo,避免循环跳转
        template 'photo', { 
            'photo_filename' => $photo, 
            'redirect_uri' => "/showphoto" 
        };
    };
    return $response;
};

2. 用Session锁替代全局变量,防止重复请求

全局变量会导致多用户场景下的冲突,改用Dancer2的Session来标记当前用户是否正在拍照,更安全可靠:

get '/photo' => sub {
    # 检查当前session是否正在执行拍照操作
    if (session('is_taking_photo')) {
        return template 'photo_wait', { 
            message => "相机正在拍照,请稍候..." 
        };
    }

    # 设置拍照状态锁
    session('is_taking_photo', 1);
    
    my $photo = $photobox->takePicture();
    
    # 释放状态锁
    session('is_taking_photo', undef);

    template 'photo', { 
        'photo_filename' => $photo, 
        'redirect_uri' => "/showphoto" 
    };
};

3. 优化前端跳转逻辑,避免循环刷新

检查你的photo模板,确保跳转逻辑是跳转到/showphoto而不是刷新/photo。比如用JavaScript跳转替代meta刷新,更可靠:

<!-- photo.tt 模板内容 -->
<div>拍照完成,即将跳转...</div>
<script>
    // 确保跳转到正确的目标页面,而非当前路由
    window.location.href = "[% redirect_uri %]";
</script>

4. 异步执行gphoto2命令,进一步减少阻塞

如果takePicture的耗时特别长,可以把gphoto2的调用改成异步执行,避免阻塞整个请求处理流程。用AnyEvent::Util来实现:

# 在Photobox.pm中修改takePicture方法
use AnyEvent::Util qw(run_cmd);
use AnyEvent;

sub takePicture {
    my $self = shift;
    my $cv = AnyEvent->condvar;

    # 先检测相机是否存在
    run_cmd ['gphoto2', '--auto-detect'], sub {
        my $output = shift;
        if ($output =~ m/usb:/) {
            # 执行拍照命令
            run_cmd [
                'gphoto2', 
                '--capture-image-and-download', 
                "--filename=" . $self->{photoPath} . $self->{filename}
            ], sub {
                my $capture_output = shift;
                if (-e $self->{photoPath} . $self->{filename}) {
                    $cv->send($self->{filename});
                } else {
                    $cv->send("no-photo-error.png");
                }
            };
        } else {
            $cv->croak("Camera not found: $output");
        }
    };

    return $cv->recv;
}

这个方法结合Dancer2的delayed使用,能最大化提升请求处理的并发能力。

总结

优先排查前端跳转逻辑是否正确,然后用Dancer2的异步响应+Session锁的组合,既能解决超时重试问题,又能避免全局变量的多用户冲突,是最稳健的解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:36:28