Scala.js 的 Vertx Eventbus 客户端

Vertx Eventbus client with Scala.js

我正在尝试在 Scala.js 项目中创建一个新的 Vertx Eventbus 实例。无论我做什么,尝试在 onopen 函数中注册处理程序时,我都会得到 INVALID_STATE_ERR。

似乎过早触发了 onopen。

示例代码: 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

}

然后,在我的应用程序中,我将其命名为:

    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)
    })
  }

您输入的 onopen 有误。应该是js.Function0[Unit].

发生的情况是 onopen 中的代码被立即执行(而不是 "on open")。

改为:

var onopen: js.Function0[Unit]=js.native

eb.onopen={ () =>
println("opening")
eb.registerHandler("activity-updates", (err, mess) => {
  val message = mess.body.toString
  println(message)
})

registerHandler 立即执行的原因是 Scala(通常)允许表达式位置的语句(因此块)。

所以如果我们只看 ep.onopen:

的赋值
eb.onopen={
  println("opening")
  eb.registerHandler("activity-updates", (err, mess) => {
    val message = mess.body.toString
    println(message)
  })
}

这会将右侧块的结果(值为 Unit)分配给 eb.onopen。实际上这意味着语句像这样执行:

println("opening")
val tmp = eb.registerHandler("activity-updates", (err, mess) => {
  val message = mess.body.toString
  println(message)
})

eb.onopen=tmp

所以你可以看到 registerHandler 甚至在 onopen 被赋值之前就被执行了。这个特性(表达式位置的语句)对于返回 Unit 的东西当然很少有用。但是,在某些情况下它非常有用。例如,临时对象:

val x = {
  val myHelper = ???
  if (myHelper) ???
  else ???
}

现在myHelper不会在范围内逃逸,很明显它只对计算x有用,以后就不会再用了。