I'm trying to create a new Vertx Eventbus instance in Scala.js project. No matter what I do, I get INVALID_STATE_ERR when trying to register handler in onopen function.
It seems like the onopen is being fired prematurely.
Example code: Eventbus.scala:
@js.native
@JSImport("vertx3-eventbus-client",JSImport.Default)
class Eventbus(url:String) extends js.Any{
def registerHandler(address:String,callback:
(js.Dynamic,js.Dynamic)=>Unit): Nothing =js.native
var onopen:Unit=js.native
}
Then, from my app, I call it:
val eb = new Eventbus("http://localhost:8080/eventbus")
eb.onopen={
println("opening")
eb.registerHandler("activity-updates", (err, mess) => {
val message = mess.body.toString
println(message)
})
}
Your typing of onopen
is wrong. It should probably be js.Function0[Unit]
.
What happens is that the code in onopen
is executed immediately (rather than "on open").
Change to this:
var onopen: js.Function0[Unit]=js.native
eb.onopen={ () =>
println("opening")
eb.registerHandler("activity-updates", (err, mess) => {
val message = mess.body.toString
println(message)
})
The reason registerHandler
got executed immediately is that Scala (in general) allows statements (and therefore blocks) in expression position.
So if we just look at the assignment to ep.onopen
:
eb.onopen={
println("opening")
eb.registerHandler("activity-updates", (err, mess) => {
val message = mess.body.toString
println(message)
})
}
This assigns the result of the block on the right hand side (of value Unit
) to eb.onopen
. Practically this means that statements get executed like this:
println("opening")
val tmp = eb.registerHandler("activity-updates", (err, mess) => {
val message = mess.body.toString
println(message)
})
eb.onopen=tmp
So you can see that registerHandler
gets executed even before onopen
is even assigned. This feature (statements in expression position) is of course rarely useful for things returning Unit
. However, there are cases where it is extremely useful. For example, temporaries:
val x = {
val myHelper = ???
if (myHelper) ???
else ???
}
Now myHelper
does not escape in scope and it is clear that it was only useful to calculate x
and not used anymore later.