Smalltalk支持使用on:retry方法重试异常,定义重试之间的行为。我想实现由另外两个操作组成的重试行为:delayInterval,maxAttempts
[ operations ]
on: Exception
maxAttempts: 10
delayInterval: 5 seconds
do: [ : e | Transcript show: 'Trying...'; cr ]
有没有优雅的方法来做到这一点?
答案 0 :(得分:5)
Carlos的方法很好,但我看到的问题是多次发送#on:do:
消息。由于Exceptions
了解#retry
消息,因此没有必要这样做。因此,我们可以在处理块内循环,而不是将所有内容都包含在循环中,如下所示:
BlockClosure >> on: aClass do: aBlock maxAttempts: anInteger
| counter |
counter := anInteger.
^self
on: aClass
do: [:ex | | result |
result := aBlock value: ex.
counter := counter - 1.
counter > 0 ifTrue:[ex retry].
ex return: result]
请注意,没有"句法"循环使用此代码。但是,执行流程将根据ex retry
消息(未到达ex return: result
行)再次评估接收块。只有当counter
到达0
时,处理程序才会放弃"放弃"并返回异常块aBlock
的值。
现在可以使用同样的想法来引入超时:
on: aClass
do: aBlock
maxAttempts: anInteger
timeout: anotherInteger
| counter timeout |
counter := anInteger.
timeout := TimeStamp now asMilliseconds + anotherInteger "dialect dependent".
^self
on: aClass
do: [:ex | | result |
result := aBlock value: ex.
counter := counter - 1.
(counter > 0 and: [TimeStamp now asMilliseconds < timeout])
ifTrue: [ex retry].
ex return: result]
同样的考虑适用于此。唯一的区别是retry
条件也考虑了超时限制。
答案 1 :(得分:1)
on: exceptionClass maxAttempts: anInteger delayInterval: seconds do: aBlock
max := anInteger.
exception := false.
[ result := self on: exceptionClass do: [ :ex | aBlock value: ex. exception := true. max := max - 1 ].
exception and: [max > 0 ] ] whileTrue: [ exception := false ].
^result
“优雅”是有争议的......