我是Scala未来的新手,我还没有找到问题的解决方案。我正在努力实现以下目标(总体描述:努力获取一个酒店列表的客人列表,分别查询每个酒店):
这是我的代码。< code>HotelReservation表示我将调用的外部API。
import com.typesafe.scalalogging.slf4j.Logging
import scala.concurrent._, ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
case class Guest(name: String, country: String)
trait HotelReservation extends Logging {
def getGuests(id: Int): Future[List[Guest]] = Future {
logger.debug(s"getting guests for id $id")
id match {
case 1 => List(new Guest("John", "canada"))
case 2 => List(new Guest("Harry", "uk"), new Guest("Peter", "canada"))
case 3 => {
Thread.sleep(4000)
List(new Guest("Harry", "austriala"))
}
case _ => throw new IllegalArgumentException("unknown hotel id")
}
}
}
object HotelReservationImpl extends HotelReservation
< code>HotelSystem拨打电话。
import com.typesafe.scalalogging.slf4j.Logging
import scala.util.control.NonFatal
import scala.util.{Failure, Success}
import scala.concurrent._, duration._, ExecutionContext.Implicits.global
class HotelSystem(hres: HotelReservation) {
def pollGuests(hotelIds: List[Int]): Future[List[Guest]] = {
Future.sequence(
hotelIds.map { id => future {
try {
Await.result(hres.getGuests(id), 3 seconds)
} catch {
case _: Exception =>
Console.println(s"failed for id $id")
List.empty[Guest]
}
}
}
).map(_.fold(List())(_ ++ _)) /*recover { case NonFatal(e) =>
Console.println(s"failed:", e)
List.empty[Guest]
}*/
}
}
还有测试。
object HotelSystemTest extends App {
Console.println("*** hotel test start ***")
val hres = HotelReservationImpl
val hotel = new HotelSystem(hres)
val result = hotel.pollGuests(List(1, 2, 3, 6))
result onSuccess {
case r => Console.println(s"success: $r")
}
val timeout = 5000
Console.println(s"waiting for $timeout ms")
Thread.sleep(timeout)
Console.println("*** test end ***")
}
1和2正在工作。所以是3,但我想我在某个地方读到了,所以尝试捕捉未来的召唤不是一个好主意,最好使用recover。但是,在这种情况下,如果我使用recover,如果出现单个故障,整个调用将失败并返回一个空列表。关于如何改进这一点有什么想法吗?
事实上,有两件事你可以做得不同:把尝试抛在脑后,不要在期货交易中使用等待。
下面是实现< code>pollGuests的一种更好的方法:
Future.sequence(
hotelIds.map { hotelId =>
hres.getGuests(hotelId).recover {
case e: Exception => List.empty[Guest]
}
}
).map(_.flatten)
这里的第一点是,您不必在 pollGuests() 中使用 Futures,
因为 getGuests()
已经为您提供了一个 Future。您只需使用 recover()
创建一个新的 Future,以便在返回 Future 时已经处理了可能的故障
第二点是您不应该使用Aetc。它会让您的代码阻塞,直到Future准备好,例如可能会冻结您的整个UI线程。我假设您使用Aetc是为了能够使用try-catch,但由于Recovery()
,您不再需要它了。
我正在使用: Scala 2.10 游戏2.1 目前,我正在使用 类,但我愿意尝试另一个 API。 我很难将多个期货的结果组合成一个列表[(String, String)]。 以下 方法成功地将单个 Future 的结果返回到 HTML 模板: 方法执行 Web 服务 API 调用并返回 Future[play.api.libs.ws.Response]。方法 向 HTML 模板返回 List[(
主要内容:抛出异常,捕获异常,实例,finally 语句,实例Scala 的异常处理和其它语言比如 Java 类似。 Scala 的方法可以通过抛出异常的方法的方式来终止相关代码的运行,不必通过返回值。 抛出异常 Scala 抛出异常的方法和 Java一样,使用 throw 方法,例如,抛出一个新的参数异常: 捕获异常 异常捕捉的机制与其他语言中一样,如果有异常发生,catch 字句是按次序捕捉的。因此,在 catch 字句中,越具体的异常越要靠前,越普遍的
Scala 的异常处理和其它语言比如 Java 类似。 Scala 的方法可以通过抛出异常的方法的方式来终止相关代码的运行,不必通过返回值。 抛出异常 Scala 抛出异常的方法和 Java一样,使用 throw 方法,例如,抛出一个新的参数异常: throw new IllegalArgumentException 捕获异常 异常捕捉的机制与其他语言中一样,如果有异常发生,catch字句是按次序
我正在阅读Scala 2.11.8留档的函数在scala.concurrent.Future模块,它说: 将副作用函数应用于这个未来的结果,并返回一个包含这个未来的结果的新的未来。 这个方法允许强制回调以指定的顺序执行。 请注意,如果其中一个链式第四个回调引发异常,则该异常不会传播到后续的第四个调用。相反,随后的第四次回调将被赋予此未来的原始值。 我不确定< code >和不传播异常到底是什么意思
在用收益结构组合期货时,有些有副作用,有些没有,我引入了竞争条件,因为取决于副作用的未来并没有将副作用的结果作为论据。 简而言之: 未来b读取由来自未来a的副作用改变的值,但是未来a不明确依赖于未来b的结果,因此可能在b完成读取之前发生。 为了解决这个问题,我的同事引入了一个虚拟函数,将b的结果作为参数并简单地将其丢弃。这样做是为了使依赖显式化。 实际代码如下: 在这种情况下,未来 b 为 带哑参
我有一个监督Akka演员,它使用路由器将消息转发给工人演员。 我有一个封装了管理程序的类,当我调用该类的方法时,它“要求”管理程序做一些事情,然后我使用< code > await . result(the future)等待结果(没有结果我无法继续)。 如果worker抛出异常,我想重新启动抛出异常的worker,我想让调用包装类的代码捕获异常。 我向路由器构造函数传递了一个< code>One