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

回调消息打印结合重试逻辑未按预期工作的问题排查

Ruby回调与重试逻辑结合的错误修复方案

常见问题根源

你遇到的报错,大概率是回调的作用域不匹配或调用方式错误:比如with_retries块内无法访问定义的callback方法,或者回调参数与定义不符。用puts正常是因为它是全局可用的方法,没有作用域问题。


方案1:将回调作为参数传入with_retries(推荐)

这种方式彻底避免作用域问题,灵活性最高:

# 带回调支持的重试封装
def with_retries(max_retries: 3, &callback)
  retries = 0
  begin
    yield
  rescue => e
    retries += 1
    # 调用回调前先检查是否存在,避免nil调用错误
    callback.call("重试第 #{retries} 次,错误:#{e.message}") if callback
    retry if retries < max_retries
    callback.call("项目处理最终失败:#{e.message}") if callback
  end
end

# 项目处理函数(模拟可能抛出错误的场景)
def process_project(proj)
  raise "模拟错误:项目 #{proj} 处理失败" if proj == 2
  puts "项目 #{proj} 处理完成"
end

# 调用示例:传入自定义回调
projects = [1,2,3]
projects.each do |proj|
  with_retries do
    process_project(proj)
  end do |msg|
    # 这里自定义回调逻辑,比如打印到日志、推送通知等
    puts "[回调消息] #{msg}"
  end
end

方案2:确保回调在作用域内可访问(类/实例场景)

如果你的代码是在类内部,需保证with_retries能访问到回调方法:

class ProjectHandler
  def initialize
    @projects = [1,2,3]
  end

  def start_processing
    @projects.each do |proj|
      with_retries do
        process_single_project(proj)
      end
    end
  end

  private

  def with_retries(max_retries: 3)
    retries = 0
    begin
      yield
    rescue => e
      retries += 1
      callback("重试 #{retries}/#{max_retries} 次:#{e.message}")
      retry if retries < max_retries
      callback("项目处理失败:#{e.message}")
    end
  end

  def process_single_project(proj)
    raise "模拟异常" if proj == 2
    callback("项目 #{proj} 处理成功")
  end

  # 自定义回调方法
  def callback(message)
    puts "[实例回调] #{Time.now} - #{message}"
  end
end

# 启动处理
ProjectHandler.new.start_processing

关键注意事项

  • 调用回调前必须做存在性检查(if callback),防止未传入回调时触发NoMethodError
  • 确保回调的参数数量、类型与定义完全匹配
  • 若回调是实例方法,不要在顶层作用域或其他实例的with_retries块中直接调用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:33:10