你能给我们一个关于“瞬态异常”行的页面引用吗?
在任何情况下,您都可以随时创建一个新的异常,这样做通常是好的,这样您就可以传输有关该故障的更多信息。当您有低级别异常并希望将其变成对用户更有意义的东西时,这尤其有用。
Ruby 中的 Throw/Catch 确实是一种非本地 goto,就像 C 中的 setjmp/longjmp,但表现更好。您可以随时使用它来转移执行很长的路要走。
显然,出于同样的原因,您不想过多地使用goto,您也不想这样做。您可能会使用它的一个重要原因是在程序需要保持运行的情况下,因此如果您发现某些类型的错误,您可能会放弃您正在做的整个工作并重新开始。
好的,这似乎不在我所拥有的任何一个版本的镐书的第 97 页上,但我明白它的意思。 ...哦,这是第三版的第157页。
首先,关于“瞬态”的业务,可能会出现一些网络问题,然后自己解决,比如说当BOFH拔掉网线再重新插上。所以,在某些情况下,你可能想给它几秒钟的时间让它安定下来,然后再试一次,然后再惊慌失措。你会怎么做?
在这种情况下,他们让您定义一种新的异常。这仅通过继承完成:
class RetryException < RuntimeError
# so this is a kind of RuntimeError which is a kind of Exception
attr: ok_to_retry
def initialize(ok_to_retry)
@ok_to_retry
end
end
所以如果出现问题,您可以提出这些新的可重试异常
raise RetryException.new(true), "transient read error"
它现在向堆栈发送某种 RuntimeError 的东西,但现在附加了附加信息,即一个标志,上面写着“是的,这可以重试”。
现在,Ruby 中有一个非常漂亮的东西:它具有重试某些东西的内置功能。所以,在堆栈的某个地方,你有这个代码:
begin
# do something that raises this exception
do_something()
rescue RetryException => detail
# if the exception is one of these retryable ones,
# catch it here, but it in detail
if detail.ok_to_retry
retry
end
# this means exactly the same as 'retry if detail.ok_to_retry`
# from the book, btw
# if it STILL doesn't work, send the exception on
raise # just re-raises the last exception
end