使用 HTTP 管道时如何干净地处理所有可能的错误?

Posted

技术标签:

【中文标题】使用 HTTP 管道时如何干净地处理所有可能的错误?【英文标题】:How to handle all possible errors cleanly when using HTTP conduit? 【发布时间】:2013-08-10 17:20:33 【问题描述】:

我有一些看起来像这样的代码:

retryOnTimeout :: IO a -> IO a
retryOnTimeout action = catch action $ \ResponseTimeout -> 
                            do putStrLn "Timed out. Trying again."
                               threadDelay 5000000
                               action 

问题是 HttpException 的其他构造函数还有很多,我一般会继续尝试,不管错误到底是什么。现在,如果我将ResponseTimeout 替换为_,则会出现编译错误,因为它无法推断出异常的类型。

我也不想为异常处理程序提供类型签名。

我知道这不是 太多 重复,但是为 _ 添加一个案例感觉不对,因为这就像在说:如果异常是 ResponseTimeout 则执行 x,但如果异常是其他任何东西 做同样的事情。有没有一种使用通配符的简洁方法,但仍然让编译器知道它是哪种类型?

【问题讨论】:

catch action $ \ (_ :: HttpException) -> do ... 怎么样?可能需要打开ScopedTypeVariables 才能编译。 啊啊啊! ScopedType 变量! GHC 甚至建议这样做,但我认为这是错误的,因为我以前从未见过扩展的确切用法。请添加为答案,以便我接受,谢谢! 您也可以编写 \~ResponseTimeout -> 来绑定类型而不进行任何实际匹配,因为 ~ 是一种惰性模式。但是,ScopedTypeVariables 是一个更好的解决方案。 【参考方案1】:

如果您不关心异常值,使用 _ 完全可以,但您需要使用 ScopedTypeVariables 或 let 子句来指定您想要的类型。

-# LANGUAGE ScopedTypeVariables #-

retryOnTimeout :: IO a -> IO a
retryOnTimeout action = catch action $ \ (_ :: HttpException) -> do
  putStrLn "Timed out. Trying again."
  threadDelay 5000000
  action

【讨论】:

以上是关于使用 HTTP 管道时如何干净地处理所有可能的错误?的主要内容,如果未能解决你的问题,请参考以下文章

如何最好地处理 Neuraxle 管道中的错误和/或丢失数据?

在多线程 HTTP 服务器中发送后,如何干净地关闭套接字?

如何干净地覆盖属性设置器?

如何在 Android 中干净地处理多个数据库表?

如何干净地使用:const char* 和 std::string?

iOS:如何干净地删除 UIButton 插座? [复制]