Scala 如何在try子句中定义的对象上调用catch子句中的方法?

Scala 如何在try子句中定义的对象上调用catch子句中的方法?,scala,Scala,我正在try-catch块中创建一个redis pubsub客户端。在try块中,通过回调初始化客户端,以将消息转发给客户端。如果向客户端发送消息时出现问题,将抛出异常,在这种情况下,我需要停止redis客户端。代码如下: try { val redisClient = RedisPubSub( channels = Seq(currentUserId.toString), patterns = Seq(), onMessage = (pubSubMessage: P

我正在
try-catch
块中创建一个redis pubsub客户端。在
try
块中,通过回调初始化客户端,以将消息转发给客户端。如果向客户端发送消息时出现问题,将抛出异常,在这种情况下,我需要停止redis客户端。代码如下:

try {
  val redisClient = RedisPubSub(
    channels = Seq(currentUserId.toString),
    patterns = Seq(),
    onMessage = (pubSubMessage: PubSubMessage) => {
      responseObserver.onValue(pubSubMessage.data)
    }
  )
}
catch {
  case e: RuntimeException =>
    // redisClient isn't defined here...
    redisClient.unsubscribe(currentUserId.toString)
    redisClient.stop()
    messageStreamResult.complete(Try(true))
    responseObserver.onCompleted()
}
问题是没有在catch块中定义redis客户机val,因为创建它时可能出现异常。我也无法将
try-catch
块移动到回调中,因为无法(我可以找到)从回调中引用redisClient对象(
this
无法解析)

为了解决这个问题,我将
redisClient
实例化为
var
块之外的
try-catch
块。然后在
try
块内,我停止客户端并将一个新的
redisPubSub
(如上所述创建)分配给
redisClient
变量。这是一个难看的黑客行为,也容易出错(例如,如果创建第二个客户端确实存在问题,catch块将尝试调用错误对象上的方法)

是否有更好的方法编写此代码,以便在尝试将消息发送到responseObserver时引发异常时,可以正确调用redisClient上的
stop()

更新

我刚刚用承诺解决了这个问题。但是有没有更简单的方法?

如果发送消息时出现问题,将不会调用异常处理程序。它用于解决设置客户端时出现的问题。本文讨论发送消息时的错误处理

至于引用客户机的回调,我认为您希望在创建客户机之后注册回调,而不是在创建回调时尝试传递回调。这里有一些这样做


可能回调将在另一个线程中运行,因此如果它使用
redisClient
,您必须小心并发性。理想情况下,回调可以通过一些参数到达客户机对象。如果没有,那么使用
volatile
可能是最简单的处理方法,尽管我怀疑如果多个回调同时失败,您最终会遇到麻烦。也许像Debashish所做的那样,使用一个actor来管理客户端连接?

因为try子句中唯一的表达式是您的
RedisPubSub
实例化,所以如果发生异常,我不知道如何在
redisClient
上调用方法。如果抛出异常,
redisClient
变量为空。@LomigMégard好吧,这就是我问题的重点,不是吗。如果由于接收消息时出错而导致运行时异常,我想关闭客户端,但无法获取对变量的引用,因为初始化变量时也可能引发异常。我编写的代码可以正常工作。我尝试实例化客户机,然后传递回调,但是客户机是一个case类,回调是不可变的。我不认为我需要使用actors,因为我正在为服务器的每个客户机创建一个redis客户机,所以一切都是不可变的。我没有在不同线程之间共享redis客户端。此外,我正在使用的库(rediscala)在幕后使用演员。关于没有调用异常处理程序,您可能是对的,不过,我会深入挖掘,谢谢。