Scala.js中的Futures

27
我尝试在Scala.js中使用Promise和Future。 Promise可以正常工作,但是一旦涉及到Future时,我会收到警告和错误信息。
尝试:
val p1 = Promise[Int]
val f1: Future[Int] = p1.future
val p2 = Promise[Int]
val f2: Future[Int] = p2.future

val res1 =  for {
   v1 <- f1
   v2 <- f2
} yield v1 + v2


val res2 = f1.flatMap(x => f2.map(y => x + y))



res1 onSuccess {
  case x: Int => g.console.log(x);

}

res2 onSuccess {
  case x: Int => g.console.log(x);

}

// callback in dom, using ScalaTags
// div(`class` := "btn  btn-default", `type` := "button", onclick := click(1, p1))
def click(i: Int, p: Promise[Int])(x: dom.MouseEvent): Unit = {
  g.console.log(i);
  try {
    p success i
  }
  catch {
    case x: Throwable => println("again")
  }
}

f1 onSuccess {
  case x: Int => 1

}

我执行sbt fastOptJs命令:

[warn] Referring to non-existent class jl_Thread$UncaughtExceptionHandler
[warn]   called from s_concurrent_impl_ExecutionContextImpl.init___ju_concurrent_Executor__F1
[warn]   called from s_concurrent_impl_ExecutionContextImpl$.fromExecutor__ju_concurrent_Executor__F1__s_concurrent_impl_ExecutionContextImpl
[warn]   called from s_concurrent_ExecutionContext$Implicits$.global$lzycompute__p1__s_concurrent_ExecutionContextExecutor
[warn]   called from s_concurrent_ExecutionContext$Implicits$.global__s_concurrent_ExecutionContextExecutor
[warn]   called from Lexample_H2$class.Lexample_H2$class__$init$__Lexample_H2__V
[warn] 

我在浏览器中看到:

uncaught exception: java.lang.RuntimeException: System.getProperty() not implemented

缺少/未实现什么?如何实现它?有没有解决方法?如何实现一个在浏览器内处理事件的ExecutionContext,使其具有意义?

1个回答

34

自Scala.js 0.6.0版本以来,标准的Scala global ExecutionContext已经可以在Scala.js中使用。您可以使用以下导入语句进行导入:

import scala.concurrent.ExecutionContext.Implicits.global

// now you get to play with Futures
在Scala.js中,它是 scala.scalajs.concurrent.JSExecutionContext.Implicits.queue的别名。该执行上下文将作业排队在标准JavaScript事件循环中。
请注意,任务是异步执行的,但不是并行执行的,因为JavaScript本身没有并行性概念。如果需要并行性,则需要使用 Web Workers,但这些对象不提供Future所需的共享内存模型。
旧的答案适用于Scala.js < 0.6.0:
scala.scalajs.concurrent.JSExecutionContext中有两个现成可用的 ExecutionContext ,在内部对象Implicits中有隐式版本。只需导入适合您的一个(可能是queue,另一个实际上不是异步的)。
import scala.scalajs.concurrent.JSExecutionContext.Implicits.queue

// now you get to play with Futures

经过短暂的研究,queue 可以使用 promises 或者 timeouts(用于不支持 promises 的老浏览器)实现。 - Suma
注意:queue 是异步的,意味着代码稍后执行(使用已解决的 Promise 或 setTimeout 上的 then),但代码不会并行运行。对于真正的“并行”(并发)任务,您需要 Web Workers,例如使用来自 github.com/nolanlawson/promise-worker 的库。或者我理解错了吗? - Suma
@Suma 你说得对。JavaScript 中没有共享内存并行处理的概念,因此 PromiseFuture 不会并行执行。如果需要并行处理,必须使用 Web Workers,但这样会失去共享内存,这从根本上改变了事物的工作方式。 - sjrd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接