scala - 当 Task 从不同的词法范围引用时,Monix TaskLocal 似乎没有反映来自 bind() 调用的值
问题描述
我有一个代码块,它是对 ScalaDoc 中为 TaskLocal 给出的代码片段的轻微修改[原文:https ://monix.io/api/3.0/monix/eval/TaskLocal.html ]。
我的代码只是将内联任务(在 for 理解范围内)替换为对在 for 理解范围之外定义的 Task 的引用。不幸的是,当我的任务运行时,它没有看到绑定,而是看到了原始值 (0)。我希望我稍微修改过的代码(如下)会产生与 ScalaDoc 中的片段相同的结果。但出乎意料的是,我得到“value3:4”,而不是 value3:200。我对 tlocal 的引用似乎得到了该 threadlocal-ish 变量的不同“版本”,该变量初始化为默认值,并且对绑定一无所知.
代码
class MonixTests extends FlatSpecLike with Matchers {
"TaskLocal" should "not make me sad " in {
val tlocal: Task[TaskLocal[Int]] = TaskLocal(0)
val readTask: Task[Int] =
tlocal.flatMap {
taskLocal: TaskLocal[Int] =>
taskLocal.read.map{ i => i * 2 }
}
val task: Task[Unit] =
for {
local <- tlocal
value1 <- local.read // value1 == 0
_ <- local.write(100)
value2 <- local.read // value2 == 100
value3 <- local.bind(200)(readTask)
value4 <- local.read // value4 == 100
_ <- local.clear
value5 <- local.read // value5 == 0
} yield {
// Should print 0, 100, 400, 100, 0 -- but value3 is not 400, but 4
println("value1: " + value1)
println("value2: " + value2)
println("value3: " + value3)
println("value4: " + value4)
println("value5: " + value5)
}
import monix.execution.Scheduler.Implicits.global
implicit val opts = Task.defaultOptions.enableLocalContextPropagation
task.runToFutureOpt
println(" TRY AGAIN a slightly different way, but no success ;^( ")
val task3: Task[Unit] =
for {
local <- tlocal
value1 <- local.read // value1 == 0
_ <- local.write(100)
value2 <- local.read // value2 == 100
value3 <- local.bind(200)(readTask)
value44 <- local.bind(200) (
tlocal.flatMap {
taskLocal: TaskLocal[Int] =>
taskLocal.read.map{i => i * 2}
}
)
_ <- local.clear
value5 <- local.read // value5 == 0
} yield {
// Should print 0, 100, 400, 100, 0 -- but value3 is not 400, but 4
println("value1: " + value1)
println("value2: " + value2)
println("value3: " + value3)
println("value4: " + value44)
println("value5: " + value5)
}
task3.runToFutureOpt
}
理由:
我想这样做的原因是因为我想将一个值绑定到我的本地线程,然后创建一个任务映射链,其中一些任务拉动本地线程的当前值,我理解它是由TaskLocal“前置”的。而且,为了清楚起见,其中一些任务是在我的代码库的其他类中定义的,而不是在任何特定的理解范围内内联。
谢谢 !/克里斯
解决方案
我现在很高兴,因为我知道如何或多或少地做我想做的事。下面的解决方案直接使用“本地”而不是 TaskLocal。但它具有在引用线程局部变量'tlocal'的代码块中可见的绑定值(200)的预期效果。
我真的不需要在“任务上下文”中做任何事情,所以这让我走上了正确的轨道。
"TaskLocal" should "not make me sad today" in {
import monix.execution.misc.Local
val tlocal = Local(0)
def doubleTlocal: Int = {tlocal.get * 2}
val value1 = tlocal.get // value1 == 0
tlocal.update(100)
val value2 = tlocal.get // value2 == 100
val value3 = tlocal.bind(200)(doubleTlocal)
val value4 = tlocal.get // value4 == 100
tlocal.clear
val value5 = tlocal.get // value5 == 0
println("value1: " + value1)
println("value2: " + value2)
println("value3: " + value3)
println("value4: " + value4)
println("value5: " + value5)
}
推荐阅读
- amazon-web-services - 如何修复 S3 存储桶和 SQS 之间的循环依赖关系?
- javascript - 对 Vue 3 中数组中的对象属性更改做出反应
- python - 在python中跟踪视频中的选定点
- netsuite - “请输入金额的值。” 在美国境外创建具有自定义价格水平的折扣发票时
- google-sheets - 如何仅获得两个重复值之一
- visual-studio-code - Vscode用“ctrl-click”打开文件和相对路径
- c++ - 检测到堆损坏(动态数组)
- c# - 无法在 HttpClient .Net 中使用 HTTP2
- pdf - 将图像添加到 Apache PDFBox 中的 PDPushButton
- python - 读取最大 4GB 的文件而不会出现 MemoryError