代码使用 fastOptJS 运行,但在 Scala.js 中使用 fullOptJS 失败

Code runs with fastOptJS but fails with fullOptJS in Scala.js

我在我的代码中捕获了错误的 asInstanceOf 引发的 UndefinedBehaviorError,如下所示:

$("button").on(
  "click",
  ".showDialog",
  (event: JQueryEventObject) => {
    event.preventDefault()
    val helpText = "Enter any number"
    js.Dynamic.global.swal(
      JC(
        title = helpText,
        text = helpText,
        `type` = "input",
        showCancelButton = true,
        closeOnConfirm = false,
        inputPlaceholder = helpText
      ),
      (input: Any) => {
        try {
          input.asInstanceOf[Boolean]
        } catch {
          case _: Throwable =>
            try {
              val correctInput = input.asInstanceOf[String].toDouble
              global.console.log("success")
            } catch {
              case _: Throwable =>
                js.Dynamic.global.swal.showInputError("Incorrect data!")
            }
        }
      }
    )
  }
)

它在 fastOptJS 上运行良好,但在 fullOptJS 上运行失败。如何使用 fullOptJS 或其他选项将此代码正确重写为 运行?

在 Scala.js 中,错误的转换不会可靠地抛出 ClassCastException,这与 Scala/JVM 不同。相反,错误的转换是 未定义的行为 ,如指定的 here。这意味着在 fullOpt 中,程序可以任意行为,特别是不允许抛出。然而,在 fastOpt 中,编译器是友好的并且可靠地抛出,但是 不是 一个 ClassCastException (因为它会给人一种错误的安全感),而是一个 UndefinedBehaviorError.

UndefinedBehaviorError 绝不能被捕获,因为捕获一个 隐藏了一个错误 在 fullOpt 中浮出水面。这是你的错误:你在 case _: Throwable => 下捕获了 UndefinedBehaviorError。请注意 catching Throwable is bad practice in Scala。相反,您应该使用 case scala.util.control.NonFatal(_) =>NonFatal 处理程序 不会 捕获 UndefinedBehaviorError,因此不会隐藏错误。

现在要解决你的问题,你根本不需要使用asInstanceOf作为type-test的手段。即使在 Scala/JVM 上,该代码也是非常糟糕的做法。改为使用模式匹配:

(input: Any) => {
  def reportIncorrectData(): Unit =
    js.Dynamic.global.swal.showInputError("Incorrect data!")

  input match {
    case input: Boolean =>
      // Here, input is a Boolean
      input
    case input: String =>
      // Here, it is a String; let's try to convert it to Double
      try {
        val correctInput = input.toDouble
      } catch {
        case _: NumberFormatException =>
          reportIncorrectData()
      }
    case _ =>
      // It is something else, always incorrect data
      reportIncorrectData()
  }
}