Повторите попытку подключения, чтобы оценить ограниченный URL-адрес, пока в Scala ничего не получится - PullRequest
1 голос
/ 25 августа 2010

Мне нужно сделать вызов GET для API REST, скорость которого ограничена. Я могу узнать текущий предел скорости, позвонив и проверив заголовки 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
}

Есть ли более чистый способ сделать это?

1 Ответ

3 голосов
/ 25 августа 2010

Вы можете сделать это хвостовой рекурсией:

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)
  }
}

Или вы можете использовать бесконечный шаблон итератора, либо необработанный:

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...