Feliz: استخدم Elmish Ringbuffer

تم إنشاؤها على ٥ ديسمبر ٢٠٢٠  ·  11تعليقات  ·  مصدر: Zaid-Ajaj/Feliz

Shmew لست متأكدًا مما إذا كان شيئًا سخيفًا ، لكنني كنت أفكر يومًا ما إذا كان من المنطقي استخدام مفردة للحارس الذي يدير رسائل جميع المكونات (سيتم وضع الرسائل في صندوق وتحتوي على إشارة إلى الهدف) . سيكون لهذا ميزة عدم تخصيص مخزن مؤقت فردي للحلقة لكل مكون وقد يسهل أيضًا تسجيل جميع الرسائل من التطبيق. ما رأيك؟

ال 11 كومينتر

نعم هذا سيكون جميلا. المشكلة الوحيدة هي أن الأمر برمته يحتاج إلى البقاء داخل شجرة React ليكون متوافقًا مع الوضع المتزامن. يمكن حل ذلك باستخدام شيء مثل السياق كطريقة لجلب التبعية ، ولكن يبدو أنه قد يكون صعبًا بعض الشيء بالإضافة إلى مطالبة المستخدم بتوفير موفر سياق و / أو بعض التهيئة الأخرى.

لست متأكدًا أيضًا من كيفية عمل السباكة مع ذلك ، حيث سيتعين علينا التعامل مع مكان استهلاك التأثيرات بالفعل. هل المكون الأول يفعل كل منهم فقط؟ أستطيع أن أرى أنه يؤثر على الأداء.

آه لقد فهمت. لم أفكر في الوضع المتزامن ، شكرًا جزيلاً على الشرح! حسنًا ، سيتم إغلاقه في الوقت الحالي وربما يمكننا إعادة الزيارة لاحقًا.

عذرًا Shmew ، ما زلت أفكر في هذا 😅 إذا لم أكن مخطئًا (على الرغم من أنني قد أكون جيدًا) ، يتم استخدام المخزن المؤقت للحلقة في Elmish لأنه يجب أن يكون متوافقًا مع الأنظمة الأساسية التي قد تعمل فيها واجهة المستخدم ووظيفة التحديث بشكل مختلف الخيوط. لكن useElmish سيعمل فقط في JS ، فلماذا لا تفعل شيئًا كهذا ؟

ربما يمكنني الإجابة بنفسي: هل المخزن المؤقت للحلقة يستخدم للتأكد من تسليم الرسائل التي تم إرجاعها بواسطة الأوامر بنفس الترتيب الذي تم فيه إنشاء الأوامر؟ هذا منطقي على الرغم من أنه قد يظل مفاجئًا للمستخدم إذا أطلق طلبي http ، يتم حظر الأول لسبب ما وهذا يمنع الاستجابة من الطلب الثاني.

لم أفكر أبدًا في الأمر كثيرًا لأن هذه هي الطريقة العادية التي يتم بها تشغيل Fable elmish.

ربما يمكنني الإجابة بنفسي: هل المخزن المؤقت للحلقة يستخدم للتأكد من تسليم الرسائل التي تم إرجاعها بواسطة الأوامر بنفس الترتيب الذي تم فيه إنشاء الأوامر؟ هذا منطقي على الرغم من أنه قد يظل مفاجئًا للمستخدم إذا أطلق طلبي http ، يتم حظر الأول لسبب ما وهذا يمنع الاستجابة من الطلب الثاني.

لا ينتظر أبدًا أي وعود ، لذلك لا ينبغي أن يكون هناك أي حظر. قد يكون قادرًا على العمل بشكل جيد فقط باستخدام مجموعة عادية.

شكرا للتحقق منShmew! آسف ، لقد أصبحت مهووسة قليلاً بالمخزن المؤقت للحلقة. أنا فقط أتذكر جميع المناقشات التي أجريناها حول التحديثات غير المتزامنة في Elmish وهذا ما يقلقني قليلاً أن لدينا جزءًا من التعليمات البرمجية لا نعرف حقًا ما الذي يفعله. كان المخزن المؤقت الحلقي IIRC عبارة عن بديل لمعالج MailboxProcessor على وجه التحديد لأنه لم يكن غير متزامن في Fable.

دائمًا ما يتم الخلط بين المستخدمين حول ما إذا كان update يعمل بشكل متزامن أم لا. تفكيري الحالي هو أن update يجب أن يكون متزامنًا وسريعًا ويجب ترك الإجراءات غير المتزامنة / البطيئة للأوامر. لا ينبغي أن يكون الاختلاف مهمًا جدًا في JS ، نظرًا لأنه لا يمكنك إنتاج سلاسل رسائل جديدة. يجب أن يكون كافيًا التفاف استدعاءات الأوامر في Promise أو setTimeout(..., 0) للتأكد من أن التنفيذ سيحدث في حلقة حدث JS التالية. على الرغم من أن الأوامر في معظم الحالات ستولد بالفعل وعودًا من تلقاء نفسها ، وإذا كنت تخطط لمنع الخيط الذي يقوم بتشغيل عاملي على عدد كبير ، فإن استخدام الأمر لن يساعد ولن يحدث فرقًا كبيرًا سواء كانت واجهة المستخدم يتم حظره في هذا الحدث أو الحدث التالي.

تتم جميع عمليات المعالجة حاليًا كوعد (داخل خطاف التأثير).

نعم ، يجدر القيام ببعض التنميط لمعرفة ما إذا كانت بنية البيانات بطيئة وما إذا كانت هناك حاجة إليها. الشيء هو أنه لطيف لأننا نريد ما يرد أولاً يصرف أولاً بدلاً من مكدس. لقد قمت بالتنميط عندما كنت أكتب كل هذا وكان سريعًا جدًا بقدر ما أستطيع أن أقول. إنه لأمر مخز أن FSSF Slack ليس لديه تاريخ لأنني أرسلت صوراً إلى @ Zaid-Ajaj (وتحدثت عن أذنيه) حول هذا الموضوع.

Shmew! لم أكن مهتمًا جدًا بالأداء (على الرغم من أن هذا مهم جدًا أيضًا) ولكن بشأن التعقيد لفهم ما يفعله useElmish بالضبط. سيكون سؤالي بشكل أساسي ، إذا كانت الأوامر مجرد وظائف تقبل وظيفة إرسال ، فلماذا نحتاج إلى بنية على الإطلاق بدلاً من مجرد إطلاق هذه الوظائف على الفور (أو ملفوفة في وعد أو setTimeout ).

دعنا نعيد فتح المشكلة ونرى كيف يمكننا تبسيط الهيكل المستخدم ، إذا لم تكن هناك حاجة إلى مخزن مؤقت للحلقة ، فيمكننا إزالته. اعتقدت أن هذه هي الطريقة لمحاكاة Program.withReactSynchronous لكنني لست متأكدًا بعد الآن. على الأقل ، أعتقد أن التنفيذ يجب أن يكون هكذا على أي حال بدون غرابة عنصر الإدخال وما إلى ذلك.

سيكون سؤالي بشكل أساسي ، إذا كانت الأوامر مجرد وظائف تقبل وظيفة إرسال ، فلماذا نحتاج إلى بنية على الإطلاق بدلاً من مجرد إطلاق هذه الوظائف على الفور (أو ملفوفة في وعد أو تعيين مهلة).

لذلك نقوم بإطلاق جميع الأوامر الجديدة على الفور ، الشيء الرئيسي هو أننا نريد التأكد من أن قائمة انتظار الرسائل هي FIFO. يمكننا القيام بذلك باستخدام قائمة عن طريق إنشاء قائمة جديدة وإلحاقها ، أو عكس القائمة الحالية ثم إضافتها إلى الرأس متبوعًا بعكس آخر. كلاهما سيفعل ما تفعله بنية البيانات هذه. أعتقد أن هذا سيكون أبطأ أيضًا ، لكن من الواضح أننا سنحتاج إلى تحديده.

اعتقدت أن هذه هي الطريقة لمحاكاة Program.withReactSynchronous ولكني لست متأكدًا بعد الآن.

هذا يتصرف بهذه الطريقة بغض النظر عن بنية البيانات الداخلية. هذه هي الحالة لأننا نستخدم الخطافات ونقوم بتحديث الحالة داخل خطاف التأثير.

إليك تطبيق FIFO غير قابل للتغيير يتسم بالكفاءة المعقولة مع القوائم. يتم استدعاء العكس فقط عندما تكون القائمة الصادرة فارغة وتكون العناصر الواردة تحتوي على عناصر لذلك يكون التنفيذ عادةً O (1). ألقيت نظرة على تطبيق useElmish الحالي ولكني لم أفهم حقًا ما كان يحدث ، لذا لم يكن هناك إغراء لتغييره.

type ListQueue<'T> private (incoming:'T list, outgoing:'T list) =
    new () = ListQueue([], [])

    member this.Push item = 
        match incoming, outgoing with
        | [], [] -> ListQueue([], [item])
        | _ -> ListQueue(item :: incoming, outgoing)

    member this.Pop () = 
        match outgoing with
        | item :: outgoing -> 
            ListQueue(incoming, outgoing), item
        | [] -> 
            match List.rev incoming with
            | [] -> failwith "Cannot Pop from an empty ListQueue"
            | item :: outgoing -> ListQueue([], outgoing), item

    member this.IsEmpty = 
        match incoming, outgoing with
        | [], [] -> true
        | _ -> false
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات