【问题标题】:Scalaz Task not startingScalaz 任务未启动
【发布时间】:2018-07-10 00:02:28
【问题描述】:

我正在尝试使用 scalaz Task 进行异步调用。

每当我尝试调用 methodA 时,出于某种奇怪的原因,虽然我得到了一个 scalaz.concurrent.Task 返回,但我从未看到第二个打印语句,这使我相信异步调用永远不会返回。为了让我开始任务,我是否缺少某些东西?

for {
    foo <- println("we are in this for loop!").asAsyncSuccess()
    authenticatedUser <- methodA(parameterA)
    foo2 <- println("we are out of this this call!").asAsyncSuccess()
} yield {
    authenticatedUser
}


def methodA(parameterA: SomeType): Task[User]

【问题讨论】:

  • 你为什么还要使用Task
  • 其实我决定用Future 改用另一条路线。谢谢。
  • 如果methodA返回的Task由于任何异常而失败,那么第二个打印语句将永远不会被执行。

标签: scala task yield scalaz


【解决方案1】:

首先,Scalaz Task 是惰性的:它不会在您创建它或从某种方法获取时启动。这是设计使然,允许Tasks 很好地结合。在您将整个程序完全组装到单个主Task 之前,它不会开始,因此当您完成后,您需要使用perform 方法之一手动启动聚合Task,例如unsafePerformSync将等待当前线程上聚合异步计算的结果:

(for {
    foo <- println("we are in this for loop!").asAsyncSuccess()
    authenticatedUser <- methodA(parameterA)
    foo2 <- println("we are out of this this call!").asAsyncSuccess()
} yield {
    authenticatedUser
}).unsafePerformSync

从原始代码中可以看出,您从未启动过任何Task。但是,您提到第一个 println 将其消息打印到控制台。这可能与 asAsyncSuccess 方法有关:我在 Scalaz 中没有找到它,所以我假设它在您代码中某处的隐式类中:

implicit class TaskOps[A](val a: A) extends AnyVal {
  def asAsyncSuccess(): Task[A] = Task(a)
}

如果你像这样编写一个辅助隐式类,它不会将有效的表达式转换为懒惰的Task 动作,尽管Task.applycall-by-name。它只会转换它的结果,恰好是Unit,因为它自己的参数a 不是按名称调用的。要按预期工作,它需要如下所示:

implicit class TaskOps[A](a: => A) {
  def asAsyncSuccess(): Task[A] = Task(a)
}

您可能还会问为什么第一个 println 打印了一些东西,而第二个没有。这与for-comprehensions desugaring 进入方法调用有关。具体来说,编译器会将你的代码变成这样:

println("we are in this for loop!").asAsyncSuccess().flatMap(foo =>
  methodA(parameterA).flatMap(authenticatedUser =>
    println("we are out of this this call!").asAsyncSuccess().map(foo2 =>
      authenticatedUser)))

如果asAsyncSuccess 不尊重预期的Task 语义,则首先会立即执行println。但是它的结果随后被包装到 Task 中,也就是说,本质上只是一个对 start 函数的包装,而 flatMap 的实现只是将这些函数组合在一起而不运行它们。因此,methodA 或第二个 println 将不会被执行,直到您调用 unsafePerformSync 或其他 perform 辅助方法。但是请注意,第二个println 仍然会比它应该根据Task 语义更早地执行,而不是更早那个

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-09
    • 2020-04-24
    • 2017-12-17
    • 1970-01-01
    • 2022-10-05
    • 1970-01-01
    • 2018-01-27
    相关资源
    最近更新 更多