Smalltalk通过使用on:retry方法来定义重试之间的行为,从而支持重试异常。我想实现由两个附加操作组成的重试行为:delayInterval,maxAttempts

[ operations ]
on: Exception
maxAttempts: 10
delayInterval: 5 seconds
do: [ : e | Transcript show: 'Trying...'; cr ]


有什么优雅的方法吗?

最佳答案

卡洛斯的方法很好,但是我看到的问题是多次发送#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条件还考虑了超时限制。

关于smalltalk - 重试Smalltalk中块的优雅方式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34815099/

10-17 02:58