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

how to pattern match event.data in scalajs

我想在我的 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 中有不同的图表,我需要通过 postMessage 发送 "add this data" 或 "clear data" 等事件。

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

相反,您需要采用 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 {
  ...
}

您可以在提取器中对此 "type test" 进行编码:

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

最后,您可能需要考虑一个 serialization/pickling 库来处理您所有的消息,例如 类。有关此类库的列表,请参阅 https://www.scala-js.org/libraries/libs.html