2017-09-15 2 views
0

저는 프레임 워크 (2.6.x)와 스칼라를 처음 사용했습니다. 미래 [JsValue]를 반환하는 함수가 있습니다. 후속 함수에서 Future [JsValue]를 어떻게 사용할 수 있습니까?후속 함수에서 미래 [JsValue] 사용하기 재생 프레임 워크 2.6x

def getInfo(): Future[JsValue] ={} 

다음 함수는 JsValue의 값을 사용하여 계산합니다.

중간에 나는 json 응답에서 값을 추출해야합니다. val currentWeight = (jsValue \ "weight").as[String].toDouble

def doubleAmounts(currentWeight: Double): Double = { 
    currentWeight*2.0 
} 

뭐죠 여기에 미래를 처리하는 적절한 방법은? json에서 weight을 얻으려면지도 또는 onComplete를 사용해야합니까?

나는 이것을 시도했지만, 이미 doubleAmounts()을 호출 한 후에 만 ​​해결한다.

val weight = getInfo() map { response => 
    if (response.toString().length > 0) (response \ "weight").as[String]) 
    else throw new Exception("didn't get response") 
} 

답변

0

문제는 당신이 Futures 얘기를 시작하는 것이 한 번, 당신은 Futures 얘기를 계속해야, 아이디어는 같은 서버가 모든 대기 및 상황 변화를 처리하는, 그래서 자기가 처리 할 수 ​​재생할 것입니다 귀하의 일부 piont에서 결과를 반환 할 것이라고 약속하십시오.

컨트롤러에서 Any을 반환하는 함수를 호출하는 대신 재생할 때 Future[Any]을 처리 할 수 ​​있습니다. 당신이 각각 다른 미래의 결과를 필요로 여러 향후 통화가있는 경우

val weight: Future[String] = getInfo() map { response => 
    if (response.toString().length > 0) (response \ "weight").as[String]) 
    else throw new Exception("didn't get response") 
} 

, 당신은지도 지옥을 피하기 위해 이해를 들어 를 사용할 수 있습니다.

def processSync(databaseServer: DatabaseServer, databaseIdentity: DatabaseIdentity): Future[String] = { 
    val info = for { 
     catalogs <- databaseSyncService.getCatalogs(databaseServer.address, databaseServer.port, databaseIdentity.login, databaseIdentity.password) 
     clubbers <- getClubbers(databaseServer.id) 
     ignoredCatalogs <- ignoredCatalogService.get(databaseServer.id) 
    } yield (catalogs, clubbers, ignoredCatalogs) 
    val result = info.map{ 
     case(catalogs, clubbers, ignoredCatalogs) => { 
     val currentCatalogs = (clubbers.map(clubber => 
      Seq(Some(clubber.mainSchema), clubber.archiveSchema, clubber.blacklistSchema, clubber.logsSchema).flatten 
     ).flatten ++ ignoredCatalogs).toSet 
     val serverCatalogs = catalogs.toSet 
     if(currentCatalogs == serverCatalogs) { 
      "synchronized" 
     } else { 
      "outOfSync" 
     } 
     } 
    }.recover{ 
     case sqlE: SQLServerException =>{ 
     logger.error(s"Conection error with ${databaseServer.name}", sqlE) 
     "connectionError" 
     } 
    } 
    for{ 
     realResult <- result 
     _ <- databaseServerRepo.updateSync(databaseServer.id, realResult) 
    } yield realResult 
    } 

가에 대한 각 값은 미래이지만, 우리가 필요한 것을 표시하기 위해 당신은 수율을 사용하기위한의 끝에서, 자신의 가치에 액세스 할 수 있습니다 노호 : 예를 들어, 다음은 좀 더 복잡한 예입니다 반환됩니다.

별례이 제어기 호출 될 수합니다 (shilouete 부분을 무시하거나, 인증 라이브러리 단순히 미래 [결과]로 복귀 형 생각할)

def sync(id: Int) = silhouette.SecuredAction.async { implicit request: SecuredRequest[DefaultEnv, AnyContent] => 
    val actions = for { 
     (server, identity) <- databaseServerService.getWithIdentity(id) 
     databaseCatalogs <- databaseSyncService.getCatalogs(server.address, server.port, identity.login, identity.password) 
     ignoredCatalogs <- ignoredCatalogService.get(id) 
     clubberIntegrations <- clubberIntegrationService.getClubbersListOrAutoFill(id, databaseCatalogs, ignoredCatalogs.map(_.name)) 
    } yield Future.successful { 
     val catalogs = databaseCatalogs.map { x => 
     val ignoredCatalogNotes = ignoredCatalogs.filter(_.name == x).map(_.note).headOption 
     DatabaseCatalog(x, ignoredCatalogNotes.getOrElse(""), ignoredCatalogNotes.isDefined) 
     } 
     Ok(web.databaseserver.views.html.databaseServerSync(request.identity, server, DatabaseServerForSync(clubberIntegrations, catalogs))) 
    } 
    actions.recover { 
     case _: SQLServerException => { 
     databaseServerService.getName(id).map(x => { 
      Redirect(web.databaseserver.controllers.routes.DatabaseServerController.list()) 
      .flashing("error" -> Messages("databaseSync.couldNotConnect", x)) 
     }) 
     } 
    }.flatMap(x => x) 
    } 

또한, 내가 깜빡하고 Future를 사용하는 함수를 처리해야하고 다른 함수를 사용하지 않는 함수를 처리해야하는 경우 후자를 Future.successful으로 변환 할 수 있고 Seq[Future[Any]]Future[Seq[Any]]으로 변환하고 다른 방법으로 미래를 처리하는 데 도움이되는 다른 함수가 있습니다.