在级联Http调用的情况下将dispatch.Http.shutdown()放在哪里 [英] Where to put dispatch.Http.shutdown() in case of cascading Http calls

查看:110
本文介绍了在级联Http调用的情况下将dispatch.Http.shutdown()放在哪里的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在哪里放置dispatch.Http.shutdown()我问如果有n个独立的Http调用,则将呼叫放置到dispatch.Http.shutdown()的位置.但是,这些n个独立的调用都在同一级别"上.

At Where to put dispatch.Http.shutdown() I asked where to place the call to dispatch.Http.shutdown() if there are n independent Http calls. Those n independent calls, however, are all on the same "level".

如何级联Http调用,而outer1outer2是彼此独立的(就像在我之前的问题中一样),但是内部调用取决于各自的结果外部呼叫.

How about cascading Http calls, whereas outer1 and outer2 are independent of each other (like in my former question), the inner calls, however, depend on the result of the respective outer call.

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
}

谢谢,/nm

更新1:感谢凯文·赖特(Kevin Wright),事情变得越来越清晰.在下面的文章中,我试图阐明为什么我需要这种级联的期货和嵌套期货上的onComplete.假设我想为经过身份验证的用户获取所有可访问的GitHub存储库的URL列表:

Update 1: Thanks to Kevin Wright, things are getting more clear. In the following I try to clarify why I need this cascading futures and the onComplete on the nested ones. Let's assume I want to get a list of URLs of all accessible GitHub repositories for an authenticated user:

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

    ???
  }
}

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

Then as soon as I have retrieved all the URLs I want to spawn a git clone process for each.

很遗憾,inner1尚未键入检查.而且,如果inner1: Option[Future[JValue]]inner2: Option[Future[JValue]],则Future.sequence(inner1 :: inner2 :: Nil)不会键入check.

Unfortunately inner1 does not yet type check. And still, if inner1: Option[Future[JValue]] and inner2: Option[Future[JValue]], then Future.sequence(inner1 :: inner2 :: Nil) does not type check.

推荐答案

如果将成功和失败的路径分开,会发现事情变得简单.

You'd find things easier if you separated the success and failure paths.

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,则几乎可以肯定,通过两次理解,它可以做得更多,重复更少.就这样,我不知道您想在其中做些什么.

If not for the onComplete of those nested operations, it could almost certainly be done far more and with less duplication using a couple of comprehensions. As it is, I have no idea what you want to do inside of them.

这篇关于在级联Http调用的情况下将dispatch.Http.shutdown()放在哪里的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆