有什么方法可以在将来的链中发挥副作用,而又不改变价值传播方式

时间:2019-04-02 11:46:12

标签: scala future

我有一个future链,它获取资源,使用它来检索一些数据,然后对该数据进行变异并返回结果(仍在将来)。

我想在返回将来的链之前释放资源,但不必插入更紧密的样板代码(即,将中间结果放入某个变量中,然后将其作为链其余部分的结果返回)。

我正在寻找类似的东西

.getResource() //returns future
   .flatMap(resource => resource.getUsageResult()) //returns future
    .FUNCTION_I_NEED(resource.free()) 
    //executes for failures and successes, doesn't change propagated exceptions or values
   .flatMap(usageResult => mutate(usageResult)) //returns future

2 个答案:

答案 0 :(得分:2)

您可以执行以下操作:

getResource()
  .flatMap(resource => {
    resource.getUsageResult()
      .map(result => {
        // .map makes sure the usage result is done
        // do your side effect here
        yourSideEffectOn(resource)
        // return the result again so you can do something with it
        result
      })
  })
  .flatMap(usageResult => mutate(usageResult))

您应该能够通过理解来简化此过程:

for {
  resource <- getResource()
  usageResult <- getUsageResult(resource)
} yield {
  yourSideEffectOn(resource) // will not wait if it returns a future
  mutate(usageResult)
}

如果我没记错的话,这也应该起作用:

for {
  resource <- getResource()
  usageResult <- getUsageResult(resource)
  _ = yourSideEffectOn(resource) // will not wait if it returns a future
} yield mutate(usageResult)

如果您还希望等待副作用完成(如果失败,请中断,然后终止),也可以flatMap副作用:

for {
  resource <- getResource()
  usageResult <- getUsageResult(resource)
  _ <- yourSideEffectOn(resource) // will wait for side effect to finish
} yield mutate(usageResult)

答案 1 :(得分:1)

您可能正在寻找andThen运算符:

something.getResource()
.flatMap(resource => resource.getUsageResult() andThen { case _ => resource.free() })
.flatMap(usageResult => mutate(usageResult))