0

我正在尝试在 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)
    })
  }
4

1 回答 1

0

你的输入onopen是错误的。应该是js.Function0[Unit]

发生的情况是代码onopen立即执行(而不是“打开时”)。

改成这样:

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,以后不再使用。

于 2017-06-23T11:09:42.937 回答