[英]Scala future strange error on completion
我剛開始使用期貨,偶然發現了一個對我來說似乎很奇怪的錯誤:
使用play-ws執行發布請求並映射結果:
wsClient.url(url).withHeaders("Content-Type" -> "application/json")
.post(payload)
.map { wsResponse =>
if (!(200 to 299).contains(wsResponse.status)) {
sys.error(s"Received unexpected status, open-cpu error ${wsResponse.status} : ${wsResponse.body}")
}
println(s"OK, received ${wsResponse.body}")
wsResponse.json.validate[Seq[MyClass]] match {
case JsSuccess(result, _) => result.map(outlierRes => Map("key" -> outlierRes.attr, "key2" -> outlierRes.attr2, "key3" -> outlierRes.val3))
case JsError(error) => throw new MyException(error.toString())
}
}
效果很好。 主體的println顯示了所有內容,並且驗證成功。
問題出在這里:aggregatedData = Await.result(theFutureFromAbove, 20.minutes)
通過交互式控制台運行時,此語句崩潰,並帶有以下內容:
MyException
at $anonfun$1.apply(<console>:44)
at $anonfun$1.apply(<console>:44)
at scala.util.Success$$anonfun$map$1.apply(Try.scala:206)
at scala.util.Try$.apply(Try.scala:161)
at scala.util.Success.map(Try.scala:206)
at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at scala.concurrent.impl.ExecutionContextImpl$$anon$3.exec(ExecutionContextImpl.scala:107)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
這將提示解析異常。
但是,通過sbt run
會有一個不同的例外:
java.lang.NullPointerException
類似於以下行: wsClient.url(baseUrl + url).withHeaders("Content-Type" -> "application/json")
它似乎是由: wsClient.close()
觸發的,好像我在將來完成之前關閉了wsClient一樣。 但是,在文檔中指出
如果手動創建WSClient,則必須在完成后調用client.close()對其進行清理。
所以我應該在哪里關閉它? 最初,我認為在Await.result
之后關閉是安全的,但這仍然Await.result
錯誤。
wsResponse.json.validate[Seq[MyClass]].fold(
error => {
println(error)
Future.failed(new MyException("parsing failed" + error))
},
result => result.map(data => Map("period" -> data.period, "amount" -> data.totalAmount, "outlier" -> data.isOutlier))
)
但這仍然無法編譯,因為Future[nothing]
與我的Future[Seq[Map[String, Any]]]
返回類型不匹配
基於https://github.com/studiodev/Mocky/blob/master/app/services/GithubRepository.scala,我終於找到了類似的東西
private def parseGistResponse(response: WSResponse): Future[GistResponse] = {
if (response.status < 400) {
logger.debug(s"<< (${response.status}) ${response.body}")
response.json.validate[GistResponse].fold(
error => {
logger.error(s"Unable to parse GistResponse: $error")
Future.failed(new RuntimeException("parse-json-failed"))
},
gistResponse => Future.successful(gistResponse))
} else {
logger.error("Unable to parse GitResponse, cannot contact WS\n" + debugResponse(response))
Future.failed(new RuntimeException("ws-error"))
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.