0

Where to put dispatch.Http.shutdown()我问dispatch.Http.shutdown()如果有n独立的 Http 调用,将调用放在哪里。然而,这些n独立的调用都在同一个“级别”上。

级联 Http 调用怎么样,而outer1outer2是彼此独立的(就像我之前的问题一样),但是内部调用取决于各自外部调用的结果。

val outer1 = dispatch.Http(... request1 ...)
val outer2 = dispatch.Http(... request2 ...)

outer1 onComplete {
  case Success(h) =>
    /*inner11*/ dispatch.Http(... request11 based on `h` ...) onComplete { ... }
    /*inner12*/ dispatch.Http(... request12 based on `h` ...) onComplete { ... }
  case Failure(e) => logger.debug(s"Error: $e")
}
outer2 onComplete {
  case Success(j) => 
    /*inner21*/ dispatch.Http(... request21 based on `j` ...) onComplete { ... }
    /*inner22*/ dispatch.Http(... request22 based on `j` ...) onComplete { ... }
  case Failure(e) => logger.debug(s"Error: $e")
}

dispatch.Future.sequence(outer1 :: outer2 :: Nil) onComplete { 
  case _ => dispatch.Http.shutdown() // <<<<< too early
}

谢谢,/纳米

更新 1:感谢 Kevin Wright,事情变得更加清晰。在下文中,我试图澄清为什么我需要这个级联期货和嵌套期货上的 onComplete。假设我想获取经过身份验证的用户的所有可访问 GitHub 存储库的 URL 列表:

object Main extends App with Logging {
  import scala.concurrent.ExecutionContext.Implicits.global

  def logFailure[T](f: Future[T]) =
    f onFailure { case x => logger.debug("Error: " + x.toString) }

  // Personal access token 
  val pat = "..."
  // GitHub API
  val github: Req = host("api.github.com").secure 
  // Http executor
  //val http = Http()

  // User profile of authenticated user
  val ur: Req = github / "user" <:< Map("Authorization" -> s"token $pat")

  // Retrieve *all* accessible repositories for authenticated user 
  Http(ur OK as.json4s.Json) flatMap { u =>
    // organizations' repos
    val inner1 = (u \ "organizations_url").toOption collect { case JString(org) =>
      Http(url(org) OK as.json4s.Json) flatMap { o =>
        (o \ "repos_url").toOption collect { case JString(rep) => 
          Http(url(rep) OK as.json4s.Json) map { _ \ "html_url" }
        }
      }
    }
    // user's repos
    val inner2 = (u \ "repos_url").toOption collect { case JString(usr) => 
      Http(url(usr) OK as.json4s.Json) map { _ \ "html_url" }
    }

    ???
  }
}

然后,一旦我检索到所有要git clone为每个 URL 生成一个进程的 URL。

不幸的是inner1还没有类型检查。而且, ifinner1: Option[Future[JValue]]inner2: Option[Future[JValue]], thenFuture.sequence(inner1 :: inner2 :: Nil)不输入检查。

4

1 回答 1

0

如果您将成功和失败路径分开,您会发现事情变得更容易。

import dispatch.Future

def logFailure[T](f: Future[T]) =
  f onFailure { case x => logger.debug("Error: " + x.toString) }

val outer1 = dispatch.Http(... request1 ...) flatMap { h =>
  val in1 = dispatch.Http(... request11 based on `h` ...)
  val in2 = dispatch.Http(... request12 based on `h` ...)
  in1 onComplete { ... }
  in2 onComplete { ... }
  Future.sequence(in1:: in2 :: Nil)            
}

val outer2 = dispatch.Http(... request2 ...) flatMap { j =>
  val in1 = dispatch.Http(... request21 based on `j` ...)
  val in2 = dispatch.Http(... request22 based on `j` ...)
  in1 onComplete { ... }
  in2 onComplete { ... }
  Future.sequence(in1:: in2 :: Nil)            
}

logFailure(outer1)
logFailure(outer2)

Future.sequence(outer1 :: outer2 :: Nil) onComplete { 
  case _ => dispatch.Http.shutdown() // <<<<< too early
}

如果不是因为onComplete那些嵌套操作,几乎可以肯定的是,使用几个推导可以做得更多,重复更少。事实上,我不知道你想在他们里面做什么。

于 2014-02-17T21:07:18.773 回答