开发环境无网络时如何挽救RestClient API调用?
我在Rails应用中编写了如下API调用代码:
class SearchFacebook FALLBACK_STARS = 5.0 def self.call begin url = "https://graph.facebook.com/v2.12/#{FACEBOOK_PAGE_ID}" response = RestClient.get(url, :params => {:access_token => FACEBOOK_ACCESS_TOKEN, :fields => "overall_star_rating"}) json = JSON.parse(response) stars = json["overall_star_rating"] rescue RestClient::ExceptionWithResponse => error stars = FALLBACK_STARS end {:stars => stars} end end
我经常在本地环境运行应用,当无网络连接时,会触发如下错误:
SocketError. Failed to open TCP connection to api.facebook.com:443 (getaddrinfo: nodename nor servname provided, or not known)
我已查阅RestClient文档但未找到解决方案,请问如何处理离线时的该异常?
嘿,这个问题我太熟悉了!你目前只捕获了RestClient::ExceptionWithResponse,但SocketError是Ruby标准库层面的底层异常,根本不属于RestClient自己定义的异常类型,所以压根没被你的rescue块接住。
给你两个靠谱的解决思路:
1. 精准捕获目标异常
直接把SocketError加到rescue的异常列表里,这样同时处理RestClient的响应异常和离线导致的连接失败:
rescue RestClient::ExceptionWithResponse, SocketError => error stars = FALLBACK_STARS
这种方式最稳妥,不会误捕其他无关异常。
2. 覆盖更多网络相关异常(按需选择)
如果你还想处理其他可能的网络问题(比如请求超时之类的),可以考虑捕获StandardError——不过要注意,这个范围很广,会接住大部分Ruby标准异常,所以只在你确定所有这些情况都应该返回fallback值的时候用:
rescue StandardError => error stars = FALLBACK_STARS end
另外,要是你想区分不同异常做不同的日志记录(方便排查问题),也可以拆成多个rescue块:
rescue RestClient::ExceptionWithResponse => error Rails.logger.error "Facebook API返回错误: #{error.message}" stars = FALLBACK_STARS rescue SocketError => error Rails.logger.error "调用Facebook API时无网络连接: #{error.message}" stars = FALLBACK_STARS
这样以后排查问题时,一眼就能看出是API本身出问题还是本地网络的锅。
对了,本地开发的话,也可以考虑用配置或者mock工具来模拟Facebook API的返回,这样离线时也不用触发异常,但如果只是单纯处理这个错误的话,上面的方法就足够啦。
内容的提问来源于stack exchange,提问作者Tintin81

