2014-11-24 15 views
20

Ho provato a utilizzare Promises e Futures in Scala.js. Prometti opere, non appena si tratta di Futures ricevo avvertimenti ed errori.Futures in Scala.js

Prova:

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 

} 

E ho in fastOptJs SBT:

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

E ho nel browser:

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

Ciò che manca/implementato? Come posso implementarlo? C'è una soluzione? Come posso implementare un ExecutionContext che ha senso gestire gli eventi con il browser?

risposta

27

Poiché Scala.js 0.6.0, lo standard globalExecutionContext di Scala è disponibile in Scala.js. È possibile importare con

import scala.concurrent.ExecutionContext.Implicits.global 

// now you get to play with Futures 

In Scala.js, è un alias per scala.scalajs.concurrent.JSExecutionContext.Implicits.queue. Questo contesto di esecuzione accoda i lavori nel ciclo di eventi JavaScript standard.

Si noti che le attività vengono eseguite in modo asincrono, ma non in parallelo, poiché JavaScript non ha alcuna nozione di parallelismo di per sé. Se è richiesto il parallelismo, è necessario utilizzare Web Workers, ma questi non forniscono il modello di memoria condivisa richiesto da Future s come tale.

Vecchio risposta applicando al Scala.js < 0.6.0

Ci sono 2 esistenti e lavorando ExecutionContext s in scala.scalajs.concurrent.JSExecutionContext, con le versioni impliciti nell'oggetto interno Implicits. Importa semplicemente quello che ha senso per te (probabilmente lo queue, l'altro non essendo effettivamente asincrono).

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

// now you get to play with Futures 
+0

Dopo una breve ricerca, il 'queue' è implementato sia utilizzando [promesse] (https://www.promisejs.org/) oppure utilizzando [timeout] (http://www.w3schools.com/ jsref/met_win_settimeout.asp) per i vecchi browser che non supportano le promesse. – Suma

+0

Nota: 'queue' è asincrono nel senso che il codice viene eseguito in un secondo momento (utilizzando quindi una Promessa risolta o setTimeout), ma il codice non viene eseguito in parallelo. Per veri compiti "paralleli" (concorrenti) occorrono Web Worker, ad esempio usando una libreria da github.com/nolanlawson/promise-worker. O sbaglio qui? – Suma

+0

@Suma Hai ragione. Non esiste il parallelismo di memoria condivisa in JavaScript, quindi 'Promise's e' Future's non vengono eseguiti in parallelo. Se è necessario il parallelismo, è necessario utilizzare Web Workers, ma si perde la memoria condivisa, che cambia fondamentalmente il modo in cui le cose funzionano a pieno titolo. – sjrd