1

我正在运行一个带有经常超时的 API 的脚本。当发生这种情况时,我正在使用begin/rescue块来获取它redo,但想在运行redo命令之前记录命令行中发生的事情。

begin
#...api query...
rescue ErrorClass
  puts("retrying #{id}") && redo
end

不幸的是,上面的脚本不起作用。只运行第一个命令。

我想强制救援块运行多行代码,如下所示:

begin
 # api query
rescue ErrorClass do ###or:# rescue ErrorClass do |e|
  puts "retrying #{id}"
  redo
 end

但那些也不起作用。

我很幸运地创建了一个单独的方法来运行,如下所示:

def example
  id = 34314
  begin
    5/0
  rescue ZeroDivisionError
    eval(handle_zerodiv_error(id))
  end
end

def handle_zerodiv_error(id)
  puts "retrying #{id}"
  "redo"
end

...这确实有效。但在我看来,它需要太多的代码行,而且它使用了 eval,根据我的导师的说法,它无论如何都不是 kosher。

4

2 回答 2

2

&&使用or会使事情变得不必要地复杂化do。该&&版本不起作用,因为puts返回nil,因此通过 的快捷评估&&,不评估要遵循的部分。如果您使用||or;代替,那么它将起作用:

begin
  ...
rescue ErrorClass
  puts("retrying #{id}") || redo
end

begin
  ...
rescue ErrorClass
  puts("retrying #{id}"); redo
end

但即使这样也没有必要。你似乎认为你需要一个块rescue来写多行,但这没有意义,因为你没有使用单行的块。没有 Ruby 构造仅在您有多行时才需要一个块。因此,只需将它们放在多行中:

begin
  ...
rescue ErrorClass
  puts("retrying #{id}")
  redo
end
于 2014-02-08T17:45:41.033 回答
1

有一个retry内置的。这个例子来自“The Ruby Programming Language”第 162 页。

require  "open-uri"

tries = 0
begin
  tries +=1
  open("http://www.example.com/"){|f| puts f.readlines}
rescue OpenURI::HTTPError => e
  puts e.message
  if (tries < 4)
    sleep (2**tries)  # wait for 2, 4 or 8 seconds
    retry             # and try again
  end
end
于 2014-02-08T17:24:09.333 回答