とある地味なブログ

プログラミングとお絵かきに関する雑記。

Scala.jsで並列処理をする

Scala.jsで並列処理したい。したくない?

オススメはWeb Workerです。Future使っても、jsの制約で結局シングルスレッド実行されるようなので。

javascriptのWeb Workerを使う

以下のGistを参考にしてください。

ポイント1

@JSExport("WorkerMain")
object WorkerMain {
  @JSExport
  def main(): Unit = {
...

@JSExportをつけて、worker.jsから

WorkerMain().main();

のように呼び出せるようにしています。

ポイント2

グローバルオブジェクトのWorkerにアクセスできるよう、 @js.nativeでオブジェクトを定義しています。

@js.native
object WorkerGlobal extends js.GlobalScope {
  def addEventListener(`type`: String, f: js.Function): Unit = js.native
  def postMessage(data: js.Any): Unit = js.native
}

ScalaのFuture, Promiseを使う

Scalaコードは普通に書きます。以下のようにScala.js用のExecutionContextimportします。

import scala.scalajs.concurrent.JSExecutionContext.Implicits.queue

可能であればjsのPromiseを使い、 そうでなければ、setTimeout(..., 0)と同様、jsの実行時タスクキューに積まれます。

jsエンジン?の実装によるんでしょうが、Chromeでは、 Future処理が終わるまで親処理が止まってしまって使い物になりませんでした。

scala.scalajs.concurrent.JSExecutionContext.Implicits.runNow
というのもありますが、現在はdeprecatedになっています。 これをimportすると、Futureは直ちに実行されます。並列実行じゃないね。