مرحبًا ، اسمي دميتري كارلوفسكي وأنا ... عاطل عن العمل. لذلك ، لدي الكثير من وقت الفراغ لتشغيل الموسيقى والرياضة والإبداع واللغات ومؤتمرات JS وعلوم الكمبيوتر. سأخبرك عن أحدث بحث في مجال التقسيم شبه التلقائي للحسابات الطويلة إلى كميات صغيرة من عدة مللي ثانية ، مما أدى إلى مكتبة مصغرة $mol_fiber
. لكن أولاً ، دعونا نلخص المشاكل التي سنحلها ..

هذه نسخة نصية من الأداء المسمى في HolyJS 2018 Piter . يمكنك إما قراءتها كمقالة ، أو فتحها في واجهة العرض التقديمي ، أو مشاهدة مقطع فيديو .
المشكلة: استجابة منخفضة
إذا كنا نريد أن يكون لدينا 60 إطارًا ثابتًا في الثانية ، فلن يكون لدينا سوى 16 إطارًا مع أجزاء من المللي ثانية للقيام بكل العمل ، بما في ذلك ما يفعله المتصفح لإظهار النتائج على الشاشة.
ولكن ماذا لو أخذنا التدفق لفترة أطول؟ ثم سيلاحظ المستخدم واجهة متخلفة ، مما يمنع الرسوم المتحركة وما شابه ذلك من تدهور تجربة المستخدم.

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

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

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

وكم سيكون رائعًا لو تم تقسيم هذا القطار إلى 10 قطارات 100 متر لكل منها ، وسيكون هناك عدة دقائق بينهما للانزلاق! لن تكون متأخرا جدا في ذلك الوقت.
إذن ما هي حلول هذه المشاكل في عالم JS الآن؟
الحل: العمال
أول شيء يتبادر إلى الذهن: دعنا فقط نضع جميع الحسابات المعقدة في خيط منفصل؟ للقيام بذلك ، لدينا آلية WebWorkers.

يتم تمرير الأحداث من دفق واجهة المستخدم إلى العامل. هناك تتم معالجتها وإرجاع التعليمات المتعلقة بما يتم تغييره على الصفحة بالفعل. وبالتالي ، فإننا نحفظ تدفق واجهة المستخدم من طبقة كبيرة من الحوسبة ، ولكن لا يتم حل جميع المشاكل بهذه الطريقة ، بالإضافة إلى إضافة مشاكل جديدة.
العمال: قضايا: (De) Serialization
يحدث الاتصال بين التدفقات عن طريق إرسال الرسائل المتسلسلة إلى دفق بايت ، ونقلها إلى دفق آخر ، وهناك يتم تحليلها في كائنات. كل هذا أبطأ بكثير من استدعاء الأسلوب المباشر داخل خيط واحد.

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

العمال: القضايا: API محدودة
واجهات برمجة التطبيقات التالية غير متوفرة لدينا في العمال ..
- DOM ، CSSOM
- قماش
- الموقع الجغرافي
- التاريخ والموقع
- مزامنة طلبات http
- XMLHttpRequest.responseXML
- النافذة
العمال: المشاكل: لا يمكن الإلغاء
ومرة أخرى ، ليس لدينا طريقة لإيقاف الحسابات في Woker.

نعم ، يمكننا إيقاف العامل بأكمله ، لكن ذلك سيوقف كل المهام فيه.
نعم ، يمكنك تشغيل كل مهمة في عامل منفصل ، ولكنها تستهلك الكثير من الموارد.
الحل: تفاعل الألياف
بالتأكيد سمع الكثيرون عن طريق FaceBook يعيدون كتابة React ، مما أدى إلى كسر جميع الحسابات فيه إلى مجموعة من الوظائف الصغيرة التي أطلقها برنامج جدولة خاص.

لن أخوض في تفاصيل تنفيذها ، لأن هذا موضوع كبير منفصل. سألاحظ فقط بعض الميزات ، والتي قد لا تناسبك ..
تفاعل الألياف: التفاعل المطلوب
من الواضح ، إذا كنت تستخدم Angular أو Vue أو إطار عمل آخر بخلاف React ، فإن React Fiber غير ذي فائدة بالنسبة لك.

تفاعل الألياف: التقديم فقط
رد فعل - يغطي فقط طبقة التقديم. يتم ترك جميع طبقات التطبيق الأخرى دون أي تكمية.

لن يوفر لك React Fiber عندما تحتاج ، على سبيل المثال ، إلى تصفية مجموعة كبيرة من البيانات حسب الظروف الصعبة.
تفاعل الألياف: تم تعطيل التكميم
على الرغم من الدعم المزعوم للقياس الكمي ، فإنه لا يزال متوقفًا بشكل افتراضي ، لأنه يكسر التوافق العكسي.

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

الحل: التكميم
دعونا نحاول تعميم نهج الألياف التفاعلية للتخلص من العيوب المذكورة. نريد أن نبقى ضمن تيار واحد ، ولكننا نقسم الحسابات الطويلة إلى كميات صغيرة ، يمكن للمتصفح من خلالها عرض التغييرات التي تم إجراؤها بالفعل على الصفحة ، وسوف نستجيب للأحداث.

أعلاه ترى حسابًا طويلًا أوقف العالم كله بأكثر من 100 مللي ثانية. ومن الأسفل - نفس الحساب ، ولكن تم تقسيمها إلى شرائح زمنية تبلغ حوالي 16 مللي ثانية ، والتي أعطت معدل 60 إطارًا في الثانية. نظرًا لأننا لا نعلم عادةً مقدار الوقت الذي ستستغرقه العمليات الحسابية ، لا يمكننا تقسيمه يدويًا إلى قطع تبلغ 16 مللي ثانية مقدمًا. لذلك ، نحتاج إلى نوع من آلية وقت التشغيل التي تقيس الوقت المستغرق لإكمال المهمة وعندما يتم تجاوز الكم ، مما يؤدي إلى إيقاف التنفيذ مؤقتًا حتى إطار الرسوم المتحركة التالي. دعونا نفكر في الآليات الموجودة لدينا لتنفيذ مثل هذه المهام المعلقة هنا ..
التزامن: الألياف - coroutines stackfull
في لغات مثل Go و D ، هناك مثل هذا المصطلح مثل "coroutine with stack" ، وهو أيضًا "ليف" أو "ليف".
import { Future } from 'node-fibers' const one = ()=> Future.wait( future => setTimeout( future.return ) ) const two = ()=> one() + 1 const three = ()=> two() + 1 const four = ()=> three() + 1 Future.task( four ).detach()
في مثال الكود ، ترى الوظيفة one
، والتي يمكنها إيقاف الألياف الحالية مؤقتًا ، ولكن لها واجهة متزامنة تمامًا. تعتبر الدالتان والثالثة والرابعة وظائف متزامنة منتظمة لا تعرف أي شيء عن الألياف. فيها يمكنك استخدام جميع ميزات جافا سكريبت بالكامل. وأخيرًا ، في السطر الأخير ، نقوم ببساطة بتشغيل الوظيفة four
في ليف منفصل.
يعد استخدام الألياف أمرًا مريحًا للغاية ، ولكن لدعمها ، تحتاج إلى دعم وقت التشغيل ، والذي لا يمتلكه معظم مترجمي JS. ومع ذلك ، بالنسبة لـ NodeJS ، هناك ملحق node-fibers
الأصلي الذي يضيف هذا الدعم. للأسف ، لا توجد متصفحات متاحة في أي متصفح.
التزامن: FSM - coroutines مكدسة
في لغات مثل C # والآن JS هناك دعم لـ "coroutines" مكدسة "أو" وظائف غير متزامنة ". مثل هذه الوظائف هي آلة حالة تحت غطاء المحرك ولا تعرف أي شيء عن المكدس ، لذلك يجب تمييزها بالكلمة الرئيسية الخاصة "غير متزامنة" ، والأماكن التي يمكن إيقافها مؤقتًا "في انتظار".
const one = ()=> new Promise( done => setTimeout( done ) ) const two = async ()=> ( await one() ) + 1 const three = async ()=> ( await two() ) + 1 const four = async ()=> ( await three() ) + 1 four()
نظرًا لأننا قد نحتاج إلى تأجيل الحساب في أي وقت ، فقد اتضح أنه يجب إجراء جميع الوظائف في التطبيق بشكل غير متزامن. هذا ليس فقط أن تعقيد التعليمات البرمجية ، ولكن يؤثر أيضًا بشكل كبير على الأداء. بالإضافة إلى ذلك ، لا تزال العديد من واجهات برمجة التطبيقات التي تقبل رد الاتصال لا تدعم الاسترجاعات غير المتزامنة. والمثال اللافت للنظر هو طريقة التصغير لأي مصفوفة.
التزامن: ألياف نصف - إعادة تشغيل
دعونا نحاول القيام بشيء مشابه للألياف ، باستخدام تلك الميزات المتاحة لنا فقط في أي متصفح حديث ..
import { $mol_fiber_async , $mol_fiber_start } from 'mol_fiber/web' const one = ()=> $mol_fiber_async( back => setTimeout( back ) ) const two = ()=> one() + 1 const three = ()=> two() + 1 const four = ()=> three() + 1 $mol_fiber_start( four )
كما ترى ، فإن الوظائف المتوسطة لا تعرف أي شيء عن الانقطاع - هذا هو JS العادي. وظيفة one
فقط تعرف عن إمكانية التعليق. لإحباط الحساب ، فإنها ببساطة تقدم Promise
كاستثناء. في السطر الأخير ، نقوم بتشغيل الوظيفة four
في ليف زائف منفصل ، والذي يراقب الاستثناءات التي تم طرحها في الداخل ، وإذا وصل Promise
، يشترك في resolve
، ثم يعيد تشغيل الألياف.
لتوضيح كيفية عمل الألياف الزائفة ، سنكتب رمزًا صعبًا ..

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

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

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

كما ترى ، بسبب إعادة التشغيل ، نخرج مرة أخرى "بدء" و "أول عمل" إلى وحدة التحكم ، ولكن لم تعد هناك "البداية الأولى" ، حيث إنها في الألياف مع ذاكرة التخزين المؤقت المعبأة في وقت سابق ، وهذا هو السبب في أن معالجها أكثر لا يسمى. عندما تمتلئ ذاكرة التخزين المؤقت لألياف walk
، يتم تدمير جميع الألياف المضمنة ، لأن التنفيذ لن يصل إليها أبدًا.
فلماذا first begin
الطباعة مرة واحدة first done
مرتين؟ كل شيء عن idempotency. console.log
- عملية غير متشابهة ، عدد المرات التي تتصل بها ، العديد من المرات ستضيف مدخل إلى وحدة التحكم. لكن الألياف التي يتم تنفيذها في ألياف أخرى هي عاطلة ، فهي تقوم فقط بتنفيذ المقبض في المكالمة الأولى ، وعند الإرجاع اللاحق مباشرة من ذاكرة التخزين المؤقت ، دون أن تؤدي إلى أي آثار جانبية إضافية.
$ mol_fiber: idempotence أولاً
دعونا نلف ملف console.log
في الالياف ، وبذلك نجعلها عاطفية ، ونرى كيف يتصرف البرنامج ..

كما ترون ، لدينا الآن في شجرة الألياف لدينا إدخالات لكل استدعاء لوظيفة log
.
$ mol_fiber: idempotence الثانية
في إعادة التشغيل التالية لألياف walk
، لم تعد المكالمات المتكررة لوظيفة log
تؤدي إلى مكالمات إلى وحدة console.log
الحقيقية ، ولكن بمجرد أن نصل إلى تنفيذ الألياف مع ذاكرة تخزين مؤقت فارغة ، console.log
استئناف المكالمات إلى وحدة console.log
.

يرجى ملاحظة أنه في وحدة التحكم ، لا نعرض الآن أي شيء غير ضروري - بالضبط ما سيتم عرضه في رمز متزامن بدون أي ألياف وتحديد كمي.
mol_fiber $: استراحة
كيف يقاطع الحساب؟ في بداية الكم ، يتم تحديد موعد نهائي. وقبل البدء في كل ألياف ، يتم التحقق مما إذا كنا قد وصلنا إليها. وإذا وصلت ، فإن Promise
يندفع ، والذي يتم حله في الإطار التالي ويبدأ كمًا جديدًا ..
if( Date.now() > $mol_fiber.deadline ) { throw new Promise( $mol_fiber.schedule ) }
$ mol_fiber: الموعد النهائي
من السهل تحديد الموعد النهائي للكم. تتم إضافة 8 مللي ثانية إلى الوقت الحالي. لماذا 8 بالضبط ، لأن هناك ما يصل إلى 16 لإعداد اللقطة؟ والحقيقة هي أننا لا نعرف مقدمًا المدة التي سيحتاج فيها المتصفح إلى العرض ، لذلك نحتاج إلى ترك بعض الوقت ليعمل. ولكن في بعض الأحيان يحدث أن المتصفح لا يحتاج إلى تقديم أي شيء ، وبعد ذلك باستخدام كمية مقدارها 8 مللي ثانية ، يمكننا إدراج كمية أخرى في نفس الإطار ، مما سيعطي تعبئة كثيفة للكمية بأقل وقت تعطل للمعالج.
const now = Date.now() const quant = 8 const elapsed = Math.max( 0 , now - $mol_fiber.deadline ) const resistance = Math.min( elapsed , 1000 ) / 10
ولكن إذا قمنا فقط برمي استثناء كل 8 مللي ثانية ، فإن التصحيح مع إيقاف تشغيل الاستثناء سيتحول إلى فرع صغير من الجحيم. نحتاج إلى بعض الآليات للكشف عن وضع مصحح الأخطاء هذا. لسوء الحظ ، لا يمكن فهم ذلك إلا بشكل غير مباشر: يستغرق الشخص حوالي ثانية لفهم ما إذا كان سيستمر في التنفيذ أم لا. وهذا يعني أنه إذا لم يعد عنصر التحكم إلى البرنامج النصي لفترة طويلة ، فعندئذ إما أن يتوقف المصحح أو أن هناك حسابًا ثقيلًا. للجلوس على كرسيين ، نضيف إلى الكم 10 ٪ من الوقت المنقضي ، ولكن ليس أكثر من 100 مللي ثانية. لا يؤثر هذا بشكل كبير على FPS ، ولكنه يقلل من تردد التوقف لمصحح الأخطاء بترتيب من الحجم بسبب التكمية.
التصحيح: حاول / قبض
بما أننا نتحدث عن تصحيح الأخطاء ، ما رأيك ، في أي مكان من هذا الرمز يتوقف المصحح؟
function foo() { throw new Error( 'Something wrong' ) // [1] } try { foo() } catch( error ) { handle( error ) throw error // [2] }
كقاعدة عامة ، يحتاج إلى التوقف حيث يتم طرح الاستثناء لأول مرة ، لكن الحقيقة هي أنه يتوقف فقط حيث تم طرحه في المرة الأخيرة ، والتي عادة ما تكون بعيدة جدًا عن مكان حدوثها. لذلك ، من أجل عدم تعقيد تصحيح الأخطاء ، يجب عدم اكتشاف الاستثناءات ، من خلال محاولة الالتقاط. ولكن حتى بدون معالجة استثناء من المستحيل.
التصحيح: أحداث لم تتم معالجتها
عادة ، يوفر وقت التشغيل حدثًا عالميًا يحدث لكل استثناء غير مكتشف.
function foo() { throw new Error( 'Something wrong' ) } window.addEventListener( 'error' , event => handle( event.error ) ) foo()
بالإضافة إلى الإرهاق ، فإن هذا الحل له عيب بحيث تقع جميع الاستثناءات هنا ومن الصعب جدًا فهم الألياف والألياف سواء حدث الحدث.
التصحيح: الوعد
الوعود هي أفضل طريقة للتعامل مع الاستثناءات.
function foo() { throw new Error( 'Something wrong' ) } new Promise( ()=> { foo() } ).catch( error => handle( error ) )
يتم استدعاء الوظيفة التي تم تمريرها إلى Promise على الفور وبشكل متزامن ، ولكن لم يتم اكتشاف الاستثناء ويوقف المصحح بأمان في مكان حدوثه. بعد ذلك بقليل ، بشكل غير متزامن ، يطلق عليه بالفعل معالج الأخطاء ، حيث نعرف بالضبط الألياف التي أعطت الفشل وأي الفشل. هذه هي بالضبط الآلية المستخدمة في $ mol_fiber.
تتبع المكدس: تفاعل الألياف
دعونا نلقي نظرة على تتبع المكدس الذي تحصل عليه في React Fiber ..

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

يتم تحقيق ذلك من خلال استخدام المكدس الأصلي والوعود والإزالة التلقائية للأمعاء. إذا كنت ترغب في ذلك ، يمكنك توسيع الخطأ في وحدة التحكم ، كما في لقطة الشاشة ، ورؤية الشجاعة ، ولكن لا يوجد شيء مثير للاهتمام.
mol_fiber $: مقبض
لذا ، لمقاطعة الكم ، يتم طرح الوعد.
limit() { if( Date.now() > $mol_fiber.deadline ) { throw new Promise( $mol_fiber.schedule ) }
ولكن ، كما قد تخمن ، يمكن أن يكون Promise أي شيء على الإطلاق - بالنسبة إلى الألياف ، بشكل عام ، لا يهم ما يمكن توقعه: الإطار التالي ، أو اكتمال تحميل البيانات ، أو أي شيء آخر ..
fail( error : Error ) { if( error instanceof Promise ) { const listener = ()=> self.start() return error.then( listener , listener ) }
تشترك الألياف ببساطة لحل الوعود وإعادة التشغيل. لكن إلقاء الوعود يدويًا والتقاطها ليس ضروريًا ، لأن الحزمة تتضمن العديد من الأغلفة المفيدة ..
$ mol_fiber: الدوال
لتحويل أي وظيفة متزامنة إلى ألياف $mol_fiber_func
سوى لفها في $mol_fiber_func
..
import { $mol_fiber_func as fiberize } from 'mol_fiber/web' const log = fiberize( console.log ) export const main = fiberize( ()=> { log( getData( 'goo.gl' ).data ) } )
هنا قمنا بجعل console.log
idempotent وتعليمنا main
مقاطعة أثناء انتظار التنزيل.
$ mol_fiber: معالجة الخطأ
ولكن كيف ترد على الاستثناءات إذا لم نرغب في استخدام try-catch
؟ ثم يمكننا تسجيل معالج الأخطاء باستخدام $mol_fiber_catch
...
import { $mol_fiber_func as fiberize , $mol_fiber_catch as onError } from 'mol_fiber' const getConfig = fiberize( ()=> { onError( error => ({ user : 'Anonymous' }) ) return getData( '/config' ).data } )
إذا أرجعنا شيئًا مختلفًا عن الخطأ فيه ، فسيكون ناتجًا عن الألياف الحالية. في هذا المثال ، إذا لم يكن من الممكن تنزيل التكوين من الخادم ، فسوف تُرجع وظيفة getConfig
التكوين بشكل افتراضي.
mol_fiber $: طرق
بالطبع ، يمكنك لف الوظائف ليس فقط ، ولكن أيضًا الأساليب باستخدام الديكور ..
import { $mol_fiber_method as action } from 'mol_fiber/web' export class Mover { @action move() { sendData( 'ya.ru' , getData( 'goo.gl' ) ) } }
هنا ، على سبيل المثال ، قمنا بتحميل البيانات من Google وتحميلها على Yandex.
mol_fiber $: وعود
لتنزيل البيانات من الخادم ، يكفي أن تأخذ ، على سبيل المثال ، fetch
الوظيفة غير المتزامنة وبنقرة من المعصم تحويلها إلى متزامن ..
import { $mol_fiber_sync as sync } from 'mol_fiber/web' export const getData = sync( fetch )
هذا التطبيق مفيد للجميع ، ولكنه لا يدعم إلغاء الطلب عندما يتم تدمير شجرة ألياف ، لذلك نحتاج إلى استخدام API
أكثر إرباكًا ..
mol_fiber $: إلغاء الطلب
import { $mol_fiber_async as async } from 'mol_fiber/web' function getData( uri : string ) : Response { return async( back => { var controller = new AbortController(); fetch( uri , { signal : controller.signal } ).then( back( res => res ) , back( error => { throw error } ) , ) return ()=> controller.abort() } ) }
يتم استدعاء الوظيفة التي تم تمريرها إلى الغلاف غير async
مرة واحدة فقط ويتم تمرير الغلاف back
إليها ، حيث تحتاج إلى التفاف الاسترجاعات. وفقًا لذلك ، في عمليات الاسترداد هذه ، يجب عليك إما إرجاع القيمة أو طرح استثناء. مهما كانت نتيجة الاستدعاء ، ستكون أيضًا نتيجة الألياف. يرجى ملاحظة أننا في النهاية نعيد وظيفة سيتم استدعاؤها في حالة التلف المبكر للألياف.
$ mol_fiber: إلغاء الرد
على جانب الخادم ، قد يكون من المفيد أيضًا إلغاء الحساب عند سقوط العميل. دعنا نطبق midleware
على midleware
التي ستخلق midleware
تشغيل midleware
الأصلية. , , , .
import { $mol_fiber_make as Fiber } from 'mol_fiber' const middle_fiber = middleware => ( req , res ) => { const fiber = Fiber( ()=> middleware( req , res ) ) req.on( 'close' , ()=> fiber.destructor() ) fiber.start() } app.get( '/foo' , middle_fiber( ( req , res ) => { // do something } ) )
$mol_fiber: concurrency
, . , 3 : , , - ..

: , . . , , .
$mol_fiber: properties
, ..
Pros:
- Runtime support isn't required
- Can be cancelled at any time
- High FPS
- Concurrent execution
- Debug friendly
- ~ 3KB gzipped
Cons:
- Instrumentation is required
- All code should be idempotent
- Longer total execution
$mol_fiber — , . — , . , , . , , , , . , . .
الروابط
Call back

: , , )
: , .
: . , .
: . , . , .
: , . , )
: , .
: - . , , .
: . , , .
: , . 16ms, ? 16 8 , 8, . , . , «».
: — . شكرا لك!
: . , . !
: , . .
: , , , , , / , .
: , .
: .
: , . mol.
: , , . , , , .
: .
: , . , $mol, , .
: , , . — . .
: - , .
: $mol , . (pdf, ) , .
: , . , .
: , ) .
: . .
: In some places I missed what the reporter was saying. The conversation was about how to use the "Mola" library and "why?". But how it works remains a mystery for me.To smoke an source code is for the overhead.
: , .
: . , . . .
: : . - (, ). , : 16?
: . . , mol_fiber … , 30fps 60fps — . — .