如何在scalajs中模式匹配event.data

时间:2017-01-21 14:55:54

标签: scala.js

我想在我的window#postMessage处理程序上匹配不同的事件,但我无法匹配本机特征。那么我怎么能解决这个问题:

@js.native
trait XY extends js.Object {
  val x: AnyVal = js.native
  val y: AnyVal = js.native
}

@js.native
trait DataEvent extends js.Object {
  val c: String = js.native                   // chart
  val s: String = js.native                   // dataSet
  val d: XY = js.native                       // xy data
  val x: Seq[XY] = js.native                  // eXtra data
}

object ChartApi extends JSApp {
  def receiveMessage(event: Any): Unit = {
    event match {
      case DataEvent => ???
      case _ => println("else")
    }

    println(s"lala $event")
  }

  def main(): Unit = {
    // add window event handler
    dom.window.addEventListener("message", (event: MessageEvent) => receiveMessage(event.data), false)
    println("Hello world!")

  }
}

我在不同的iframe中有不同的图表,我需要发送类似&#34的事件;添加此数据"或者"清除数据"通过postMessage。

1 个答案:

答案 0 :(得分:1)

JS traits在运行时没有标识,这就是为什么你不能直接测试任意对象是否是JS特征的实例的原因。

相反,您需要采用JS方式,并测试是否存在唯一标识由特征表示的接口的字段,以及其他可能的选择。例如:

if (event.hasOwnProperty("d")) {
  // it must be a DataEvent, because the alternatives do not have a 'd' field
  val e = event.asInstanceOf[DataEvent]
  ...
} else {
  ...
}

通常,我们不喜欢这样做。因此,在具有这种类型的消息的消息传递协议中,我们通常具有明确的messageType字段或类似的字段。如果您确保所有DataEvent条消息都为messageType = "data"字段,则可以执行以下操作:

if (event.messageType == "data") {
  val e = event.asInstanceOf[DataEvent]
  ...
} else {
  ...
}

您可以对此进行编码"类型测试"在提取器中:

object DataEvent {
  def unapply(event: Any): Option[DataEvent] =
    if (event.messageType == "data") Some(event.asInstanceOf[DataEvent])
    else None
}
然后你可以在模式匹配中使用

event match {
  case DataEvent(event) => ???
  case _ => println("else")
}

最后,您可能需要考虑使用序列化/ pickle库来将所有消息作为案例类来处理。有关此类库的列表,请参阅https://www.scala-js.org/libraries/libs.html