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
相关产品推荐
相关产品推荐

