如何在scala-js中正确使用js.Dynamic类型的返回值?

时间:2015-07-10 16:09:58

标签: firebase scala.js

我试图在scala-js应用中使用firebase。 我正在努力将firebase-result转换为scala。

我使用了明确类型的repo的firebase.d.ts文件来创建scala-classes。通过一些调整,它到目前为止工作正常。

我使用此示例代码从firebase sample-repository中获取一些数据:

<html>
    <head>
        <script src='https://cdn.firebase.com/js/client/2.2.1/firebase.js'></script>
        <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'></script>
    </head>
    <body>
    <script>
        var myDataRef = new Firebase('https://gjauaudjwdc.firebaseio-demo.com/');

        myDataRef.on('value', function (snapshot) {
            console.log("   received value: ", snapshot.val());
            console.log("toString'ed value: ", snapshot.val().toString());
        });

    </script>
    </body>
</html>

日志正确记录收到的快照(json-object)。

   received value:  Object {-ImBnHMmOnndxre8XSkl: Object, -ImBnI0WLch7L7ndl6Qd: Object}
toString'ed value:  [object Object]

这是scala-js-version

package example

import de.flwi.firebase._

import scala.scalajs.js

object ScalaJSExample extends js.JSApp {

  def main(): Unit = {

    val rootRef: Firebase = FirebaseFactory.create("https://gjauaudjwdc.firebaseio-demo.com/")

    rootRef.on1("value", callback = { (snapshot: FirebaseDataSnapshot) => {
        println(snapshot.value())
      } 
    })    
  }    
}

当我使用scala-js的Firebase-wrapper尝试相同的操作时,我只会将[object Object]写入控制台。就像在第一个例子中对接收到的值调用toString()时一样。

相应的特征看起来像这样(缩短):

trait FirebaseDataSnapshot extends js.Object {
  @JSName("val") def value(): js.Dynamic = js.native
}

trait FirebaseQuery extends js.Object {
  @JSName("on") def on1(eventType: String, callback: js.Function1[FirebaseDataSnapshot, Unit], cancelCallback: js.Function1[js.Any, Unit] = ???, context: Object = ???): js.Function1[FirebaseDataSnapshot, Unit] = js.native
  @JSName("on") def on2(eventType: String, callback: js.Function2[FirebaseDataSnapshot, String, Unit], cancelCallback: js.Function1[js.Any, Unit] = ???, context: Object = ???): js.Function2[FirebaseDataSnapshot, String, Unit] = js.native

}

@JSName("Firebase")
trait Firebase extends FirebaseQuery {

}

import scala.scalajs.js.Dynamic.{global => g, newInstance => jsnew}

@JSName("Firebase")
object FirebaseFactory {
  def create(url: String): Firebase = jsnew(g.Firebase)(url).asInstanceOf[Firebase]

}

有没有人能指出我正确的方向如何以正确的方式处理js.Dynamic,比如迭代jsObject的值?

我上传了project to github两个例子(index-with-js.html和index.fastopt.html)

2 个答案:

答案 0 :(得分:0)

我建议将对象解释为js.Dictionary

trait FirebaseDataSnapshot extends js.Object {
  @JSName("val") def value(): js.Dictionary[js.Any] = js.native
}

js.Dictionary拥有scala.Map的所有方法(隐式添加)。所以你现在可以简单地写一个for循环(或调用get):

rootRef.on1("value", callback = { (snapshot: FirebaseDataSnapshot) => {
    // iterate over key value pairs
    for ((key, value) <- snapshot) println(key)

    // get a particular key
    snapshot.get("foo") // returns an Option
  } 
})

答案 1 :(得分:0)

@ gzmo的答案在一般情况下是正确的。但是如果你知道返回对象的结构是什么(我不知道Firebase,但是数据库调用通常也是如此 - 你确切知道应该在结果中定义哪些字段) ,您可以为结果定义外观特征,并使用asInstanceOf []将快照投射到该特征。我可能建议将其作为一种更强类型的方法,如果结果字段相当一致:外观通常更容易在Scala代码中使用。

这些答案不是/或 - 例如,您可以将其视为字典用于记录目的,然后将其转换为外观,然后再将其交给更高级别的代码。