Frage

In unserem Projekt verwenden wir ReactiveMongo mit Play 2.2.1.

Das Problem besteht darin, dass der Datenstrom in einer Form von Enumerator[A], zurückgegeben von ReactiveMongo ist eigentlich ein Stream von Wertobjekten, die nicht durch Kommas getrennt sind und keine Stream-Anfangs- und Endanmerkungen haben, die als Array-Öffnungs- und Schließanweisungen behandelt werden können.

Dies schafft ein Problem für JSON Verbraucher JS client, da das erwartete Format ist[A1,A2, ...]

Also sprangen wir in Reifen und verwandelten unsere Enumeratee[A] Zu Enumerator[String], mit Prüfung, ob es das erste Element ist oder nicht:

    var first:Boolean = true
    val aToStrs = (as.map(a => {
        if(first) {
            first = false;
            Json.stringify(Json.toJson(a))
        } else {
            "," + Json.stringify(Json.toJson(a))
        }
   }))
   Ok.chunked(
       Enumerator.enumInput(Input.El("[")) andThen
       aToStrs andThen
       Enumerator.enumInput(Input.El("]")) andThen
       Enumerator.enumInput(Input.EOF)
   )

Das funktioniert, fühlt sich aber an, als würde man das Rad erfinden.

Gibt es eine bessere Lösung für dieses häufige Problem?

War es hilfreich?

Lösung

Wenn Sie Comet oder EventSource verwenden, müssen Sie keine Möglichkeit zur Generierung der Ausgabe manuell erstellen und können die Antwort tatsächlich Element für Element im Client analysieren.Wenn Sie mit einem Array antworten, müssen Sie entweder Ihren eigenen Parsing-Code schreiben oder warten, bis alles auf der Client-Seite angekommen ist, bevor Sie den Build-Int-JSON-Parser in Ihrem JavaScript verwenden können.

Das Streamen mit dem EventSource-Protokoll ist mit Play ziemlich einfach. Sie sollten in der Lage sein, Folgendes zu tun:

implicit val cometEncoder = new Comet.CometMessage[JsValue](_.toString)
Ok.chunked(yourEnumerator &> EventSource()).as(EVENT_STREAM)

Und dann im Client-HTML:

<script type="text/javascript">
  var es = new EventSource(jsRouter.controllers.Application.streamIt().url)

  es.addEventListener("message", function (event) {
    var item = JSON.parse(event.data)
    // ... do something with the json value ...
  })
</script>

Ein Beispiel hierfür finden Sie in den Play-Beispielprojekten, die Sie sich vielleicht auch ansehen möchten $YOUR_PLAY_DIR/samples/scala/eventsource-clock/

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top