显式地将Any / Blob转换为ArrayBuffer仍然给我一个我无法处理的Blob

时间:2017-01-28 23:20:42

标签: javascript dom casting scala.js

在我的websocket上,我希望从服务器到客户端的二进制消息(另一种方式可行)。我想将其转换为Array[Byte]以进一步将其作为protobuf-message

处理
ws.onmessage = {
  (event: MessageEvent) =>
    val msg = event.data.toString
    dom.window.console.log(msg) 

    val x = event.data.asInstanceOf[ArrayBuffer]
    val df = new DataView(x)
    dom.window.console.log("result")
    dom.window.console.log(bin2User(df).toString)
}

private def bin2User(data: DataView): User = {
    val bytes = new Array[Byte](data.byteLength)

    for(index <- 0 to data.byteLength) {
      bytes(index) = data.getInt8(index)
    }

    User.parseFrom(bytes)
  }

现在dom.window.console.log(msg)给了我

  

[object Blob]

     

Blob {size:9,type:“”}

我希望x属于ArrayBuffer类型,因为显式强制转换,但唉,它不是,因为我得到了

  

TypeError:DataView:期望的ArrayBuffer,得到了Blob

我怎样才能克服这个?

我尝试过:

val fr = new FileReader
fr.readAsArrayBuffer(event.data.asInstanceOf[Blob])
val y = fr.result.asInstanceOf[ArrayBuffer]
dom.window.console.log(y)

但这会为null以及

打印y
  

TypeError:y不是对象

2 个答案:

答案 0 :(得分:1)

你几乎就在那里:FileReader是异步的,所以你必须:

val fr = new FileReader
fr.onload = { _ =>
  val y = fr.result
  dom.window.console.log(y)
}

fr.readAsArrayBuffer(event.data.asInstanceOf[Blob])

这实际上是this response的翻译示例。

您可能希望将其包装在未来的API中:

import scala.concurrent.Promise

def blob2ArrayBuffer(blob: Blob): Future[ArrayBuffer] = {
  val result = Promise[ArrayBuffer]()
  val fr = new FileReader
  fr.onload = { _ => result.success(fr.result) }
  fr.readAsArrayBuffer(blob)
  result.future
}

答案 1 :(得分:1)

有些人已经指出,设置ws.binaryType = "arraybuffer"也足够了。

这样做:

 ws.onmessage =
      {
        ws.binaryType = "arraybuffer"

        (event: MessageEvent) => 

            val msg = event.data.asInstanceOf[ArrayBuffer]
            dom.window.console.log(msg)

结果

  

ArrayBuffer {byteLength:9}