2014-11-24 7 views
20

Ich habe versucht, Versprechen und Futures in Scala.js zu verwenden. Promise funktioniert, sobald es zu Futures kommt, bekomme ich Warnungen und Fehler.Futures in Scala.js

Versuchen:

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 

} 

Und ich in sbt fastOptJs erhalten:

[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] 

Und ich bekomme im Browser:

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

Was fehlt/unimplemented? Wie kann ich es implementieren? Gibt es eine Problemumgehung? Wie kann ich einen ExecutionContext implementieren, der für die Behandlung von Ereignissen im Browser sinnvoll ist?

Antwort

27

Seit Scala.js 0.6.0 ist der Standard globalExecutionContext von Scala in Scala.js verfügbar. Sie importieren können es mit

import scala.concurrent.ExecutionContext.Implicits.global 

// now you get to play with Futures 

In Scala.js, es ist ein Alias ​​für scala.scalajs.concurrent.JSExecutionContext.Implicits.queue. Dieser Ausführungskontext reiht Jobs in der Standard-JavaScript-Ereignisschleife ein.

Beachten Sie, dass Tasks asynchron, aber nicht parallel ausgeführt werden, da JavaScript an sich keine Parallelität hat. Wenn Parallelität erforderlich ist, müssen Web Workers verwendet werden, aber diese bieten nicht das Shared-Memory-Modell, das für Future s erforderlich ist.

Alte Antwort < 0.6.0

Es gibt 2 vorhandene und Arbeits ExecutionContext s in scala.scalajs.concurrent.JSExecutionContext, mit impliziten Versionen im inneren Objekt Implicits Scala.js Anwendung. Importieren Sie einfach den, der für Sie Sinn macht (wahrscheinlich queue, der andere ist nicht wirklich asynchron).

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

// now you get to play with Futures 
+0

Nach einer kurzen Forschung, die 'queue' umgesetzt wird entweder mit [Versprechen] (https://www.promisejs.org/) oder mit [Timeouts] (http://www.w3schools.com/ jsref/met_win_settimeout.asp) für alte Browser, die Versprechen nicht unterstützen. – Suma

+0

Hinweis: 'queue' ist asynchron in dem Sinne, in dem der Code später ausgeführt wird (mithilfe eines aufgelösten Promise oder setTimeout), der Code wird jedoch nicht parallel ausgeführt. Für echte "parallele" (gleichzeitige) Aufgaben benötigen Sie Web Worker, z. B. eine Bibliothek von github.com/nolanlawson/promise-worker. Oder liege ich hier falsch? – Suma

+0

@Suma Sie haben Recht. Es gibt keine Shared-Memory-Parallelität in JavaScript, daher werden 'Promise's und' Futures' nicht parallel ausgeführt. Wenn Parallelität erforderlich ist, müssen Sie Web Workers verwenden, aber Sie verlieren den gemeinsamen Speicher, was die Funktionsweise der einzelnen Elemente grundlegend ändert. – sjrd