تخيل القيام بـ 10 مهام بشكل مستمر ؛ ربما لا نتعب بعد هذه المهام العشر ، ولكن ماذا عن 50 مهمة أو 100 مهمة؟ لا يمكننا حتى القيام بهذا القدر من المهام بشكل مستمر وبدون جدولة.
ولكن هناك حل واحد لذلك ، وهو تحديد المواعيد. من خلال الجدولة ، يمكننا القيام بأي قدر من المهام بسهولة ، وسنعمل على زيادة إنتاجيتنا. على سبيل المثال ، بعد كل 10 مهام ، نأخذ قسطًا من الراحة لمدة 5 دقائق ، أو أفضل من ذلك ، يمكننا الاستمرار في أداء المهام حتى نتعب ، ثم نأخذ قسطًا من الراحة ونستمر في القيام ببقية المهام.

الشيء نفسه ينطبق على جافا سكريبت. على سبيل المثال ، هذا الرمز سوف يحظر موضوعنا لمدة 5 ثوان ، وسوف يتوقف كل شيء عن العمل.
let current = Date.now() while (Date.now() < current + 5 * 1000) { console.log(`I'm blocking your thread for 5sec`) }
لكن هذا ليس عدلاً ، لأنه ليس عملاً شاقًا. يمكن للمكتبات مثل Reactjs التعامل مع أعمال أثقل بمقدار 100 مرة دون حظر المتصفح. والسبب هو أن مثل هذه المكتبات تستخدم الجدولة.
الجدولة
الجدولة حول:
- قائمة انتظار العمل: قائمة الأعمال التي نريد جدولتها وإنجازها
- المهام الصغيرة والكبيرة: نوعان مختلفان من المهام يمكننا نقل المهام الخاصة بنا إلى إحدى هذه المراحل ، بحيث يتعامل معها المتصفح لاحقًا (مهمة صغيرة) أو على الفور (مهمة أو مهمة ماكرو)
“أولاً ، في كل مرة يتم فيها إنهاء مهمة (مهمة ماكرو) ، تتحقق حلقة الحدث لمعرفة ما إذا كانت المهمة تعيد التحكم إلى تعليمات JavaScript البرمجية الأخرى. إذا لم يكن الأمر كذلك ، فسيتم تشغيل جميع المهام الدقيقة في قائمة انتظار المهام الدقيقة. تتم معالجة قائمة انتظار المهام الدقيقة عدة مرات لكل تكرار لحلقة الحدث ، بما في ذلك بعد معالجة الأحداث وعمليات الاسترجاعات الأخرى.”

حان الوقت الآن لجدولة بعض الأشياء ، دعنا نرى.
تنفيذ
قبل أي شيء، تخيل أن لدينا العديد من أصناف العمل المهمة في قائمة انتظار لدينا ، مثل هذا:
function expensive() { console.log('I wanna block the event loop') } const workQueue = new Array(1000000).fill(expensive); // [expensive, expensive, ...] // 1000000 amount of work units 🤯🤯 // workQueue.map(job => job()) will destroy the event loop and everything will stop working
إذا أردنا جدولة هذه الأقسام، فعلينا النظر في أمرين: أولا، موعد نهائي إنطلاق وتشغيل الأقسام. إذا تم ذلك ، فإننا نستسلم للمتصفح للتعامل مع أحداث إدخال المستخدم ثم نعود لتشغيل باقي الوحدات ؛ ثانيًا ، حدث إدخال المستخدم (النقر ، الكتابة ، …) عند تشغيل الأقسام ، لذلك نعود فورًا إلى المتصفح مرة أخرى ، للتحقق مما إذا كان لدينا أحداث إدخال المستخدم ، نستفيد isInputPending.
دعنا نحدد وقت الموعد النهائي ، والذي أفضل تعيينه كإطار واحد.
const DEADLINE_TIME = 1000 / 60 // 1000ms / 60frames
إنشاء دالة الجدولة
في الوقت الحالي ، نحتاج إلى إنشاء دالة الجدولة.
function schedule() { const DEADLINE = performance.now() + DEADLINE_TIME; while (workQueue.length > 0) { if (navigator?.scheduling?.isInputPending() || performance.now() >= DEADLINE) { // Yield to the browser if we have to handle an input event, or we're out of time. setTimeout(schedule); // re-running the schedule function later as a macro task return; // stop } // execute the current work unit let job = workQueue.shift(); job(); } }
لذلك إذا كان لدينا حدث إدخال مستخدم في انتظار أو نفد الوقت ، فإننا نضع وظيفة الجدول الزمني لدينا على جزء مختلف من حلقة الحدث (setTimeout) ، بحيث يمكن للمتصفح التعامل مع حدث الإدخال والأشياء الأخرى التي تسبقه ؛ بعد ذلك ، سيتم إعادة تشغيله والسماح لوظيفة الجدولة بتنفيذ باقي الوحدات إن أمكن.
الآن ، إذا حاولت تشغيل وظيفة الجدول الزمني ، فلن يمنع مليون سجل كل شيء من العمل ، وسيعمل كل شيء بشكل جيد.
schedule()
هذا كان كل شيء، سهل وسريع!
آمل أن يحظى هذا المقال بإعجابكم.
This article is useful for me
1+ 4 People like this post