我需要对速率有限的REST api进行GET调用。我可以通过拨打电话和检查HTTP标头来了解当前的速率限制。如果我超过了我的速率限制,我应该等一会儿再重试。我想写一些类似的东西:
val conn = connect(url, _.getHeaderField("X-RateLimit-Remaining").toInt > 0, 500)
我有一个使用var,while循环和一些重复代码的工作解决方案,但它感觉很笨:
def connect(url: String, succeeded: URLConnection=>Boolean, waitMillis: Int) = {
var conn = new URL(url).openConnection
while (!succeeded(conn)) {
Thread.sleep(waitMillis)
conn = new URL(url).openConnection
}
conn
}
有更简洁的方法吗?
答案 0 :(得分:3)
你可以让它尾递归:
def connect(url: String, succeeded: URLConnection=>Boolean, wait: Int): URLConnection = {
val conn = new URL(url).openConnection
if (succeeded(conn)) conn
else {
Thread.sleep(wait)
connect(url,succeeded,wait)
}
}
或者你可以使用无限的迭代器模式,raw:
def connect(url: String, succeeded: URLConnection=>Boolean, waitMillis: Int) = {
val tries = Iterator.continually( new URL(url).openConnection )
tries.dropWhile(
conn => if (succeeded(conn)) false else { Thread.sleep(waitMillis); true }
).next
}
或通过在返回选项的等待中包装URL调用(如果您希望在其他位置处理选项,则特别有用;不确定是否要在那里或外部嵌入等待):
def attemptConnect(url: String, succeeded: URLConnection=>Boolean, waitMillis: Int) = {
val conn = new URL(url).openConnection
if (succeeded(conn)) Some(conn)
else { Thread.sleep(waitMillis); None }
}
def connect(url: String, succeeded: URLConnection=>Boolean, waitMillis: Int) = {
val tries = Iterator.continually( attemptConnect(url,succeeded,waitMillis) )
tries.dropWhile(_.isEmpty).next
}