Scala.js 全局 WebSocket -> InvalidStateError

Scala.js global WebSocket -> InvalidStateError

我正在尝试创建一个全局 websocket 引用,我想稍后将其扩展到自动重新连接。

但是我不确定为什么这没有按预期工作:

val uri = s"ws://localhost:1337/websocket"
var websocket: Future[WebSocket] = initWebSocket()

 def initWebSocket() : Future[WebSocket] = {
    val ws = new WebSocket(uri)

    ws.onopen =
      {
        (event: Event) => log("Websocket connection established")
      }

    ws.onmessage =
      {
        (event: MessageEvent) => log("Message received")
      }

    ws.onclose =
      {
        // TODO wait some seconds before trying to reconnect
        (event: CloseEvent) =>
          log("Close event received")
        //  this.websocket = new WebSocket(uri)
      }

    Future(ws)
}

我完全知道(草图)onclose 现在的东西绝对是胡说八道!

def main(): Unit = {
  websocket.onComplete {
    case Failure(x) => println("Epic fail!")
    case Success(x) => {
      x.send("Test")
    }
  }   
}

我得到的只是

scala.scalajs.js.JavaScriptException: InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

Websocket connection established

The connection to ws://localhost:1337/websocket was interrupted while the page was loading.

Close event received

不是甚至想知道为什么!

onopen 被称为太晚了......但是如何优雅地解决这个问题?我基本上需要确保 ws.onopen 在返回 websocket 之前被调用。我不想阻止而是使用一些 PromiseFuture

嗯。似乎您需要 Future 在 onopen 之后才解析。所以我可能会像这样重写它(请注意,我还没有尝试编译它——它可能需要调整):

def initWebSocket() : Future[WebSocket] = {
  val promise = Promise[WebSocket]
  val ws = new WebSocket(uri)

  ws.onopen =
  {
    (event: Event) => {
      log("Websocket connection established")
      promise.complete(Success(ws))
    }
  }

  ws.onmessage =
  {
    (event: MessageEvent) => log("Message received")
  }

  ws.onclose =
  {
    // TODO wait some seconds before trying to reconnect
    (event: CloseEvent) =>
      log("Close event received")
    //  this.websocket = new WebSocket(uri)
  }

  promise.future
}

这样,Future 不会立即完成——它会在 希望它完成时完成,也就是在你获得 onopen确认。有道理吗?