كيفية إرجاع Enumerator of JSON من ReactiveMongo في Play 2
-
21-12-2019 - |
سؤال
في مشروعنا نستخدم ReactiveMongo
مع Play 2.2.1
.
المشكلة هي أن دفق البيانات في شكل من أشكال Enumerator[A]
, ، عاد بواسطة ReactiveMongo
هو في الواقع دفق من كائنات القيمة، التي لا يتم فصلها بفواصل، ولا تحتوي على تعليقات توضيحية لبداية الدفق ونهايته، والتي يمكن التعامل معها على أنها عبارات فتح وإغلاق للمصفوفة.
وهذا يخلق مشكلة ل JSON
مستهلك JS client
, ، حيث أن التنسيق المتوقع هو[A1,A2, ...]
لذلك قفزنا في الأطواق، وقمنا بتحويلنا Enumeratee[A]
ل Enumerator[String]
, مع التحقق مما إذا كان هو العنصر الأول أم لا:
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)
)
هذا ينجح، لكنه يبدو وكأنه اختراع العجلة.
هل هناك حل أفضل لهذه المشكلة الشائعة؟
المحلول
إذا كنت تستخدم Comet أو EventSource، فلن تضطر إلى صياغة طريقة لإنشاء المخرجات وستتمكن أيضًا من تحليل عنصر الاستجابة للعنصر الموجود في العميل.قد تجبرك الاستجابة بمصفوفة على كتابة كود التحليل الخاص بك أو الانتظار حتى يصل كل شيء إلى جانب العميل قبل أن تتمكن من استخدام محلل البنية int JSON في JavaScript.
يعد البث باستخدام بروتوكول EventSource أمرًا سهلاً للغاية أثناء اللعب، ويجب أن تكون قادرًا على القيام بشيء مثل:
implicit val cometEncoder = new Comet.CometMessage[JsValue](_.toString)
Ok.chunked(yourEnumerator &> EventSource()).as(EVENT_STREAM)
ثم في 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>
يوجد مثال على ذلك في نماذج المشروعات المسرحية التي قد ترغب في الاطلاع عليها أيضًا $YOUR_PLAY_DIR/samples/scala/eventsource-clock/