مقدمة: لماذا موقعك "بطيء" ومن المسؤول عن ذلك
\n\nتخيل مطعمًا حيث نادل واحد يستقبل الطلبات ويوزع الطعام ويغسل الأطباق ويحسب الإيرادات في نفس الوقت. فوضى، أليس كذلك؟ هذا تقريبًا ما يفعله JavaScript أحادي الخيط إذا لم تتم إدارة المهام بشكل صحيح. عندما نكتب كودًا يفعل كل شيء دفعة واحدة - تحميل البيانات، معالجة النقرات، رسم الرسوم المتحركة - يتجمد المتصفح ويرى المستخدم واجهة "متفكرة".
\n\nاليوم سنفهم كيف تساعد قوائم المهام في JavaScript في تحويل هذه الفوضى إلى نظام منظم. ستتعلم كيف يوزع Event Loop الأولويات، وكيف تختلف المهام الصغيرة عن المهام الكبيرة، وكيف تسمح المهام الخلفية في JavaScript بعدم حظر الخيط الرئيسي. في النهاية، تنتظرك أمثلة عملية يمكنك تطبيقها فورًا في مشروعك.
\n\nكيف يعمل Event Loop: قائد أوركسترا المهام
\n\nفي قلب كل التزامن يوجد Event Loop JavaScript. هذه آلية تدور بلا نهاية وتسأل: "هل هناك شيء للتنفيذ؟ والمهام الصغيرة؟ والتقديم؟". إذا تساءلت يومًا لماذا لا يتم تنفيذ setTimeout فورًا بينما يتم تنفيذ Promise.then بشكل شبه فوري - فالإجابة تكمن هنا.
مكدس الاستدعاءات (Call Stack)
\nهذا هو المكان الذي تذهب إليه الدوال للتنفيذ الفوري. طالما أن المكدس مشغول، لن يحدث أي شيء آخر. إذا كانت وظيفتك تحسب مليون رقم - سيتجمد المتصفح لأن المكدس لن يتحرر.
\n\nقائمة المهام الكبيرة (Macrotask Queue)
\nهنا تذهب setTimeout، setInterval، أحداث DOM (النقرات، التمرير)، تحميل الموارد. يأخذ Event Loop مهمة واحدة من هذه القائمة، ينفذها، ثم يتحقق من المهام الصغيرة، ثم يعرض الصفحة - ثم يأخذ المهمة الكبيرة التالية.
قائمة المهام الصغيرة (Microtask Queue)
\nوهذه هي مملكة Promise، queueMicrotask، MutationObserver. المهام الصغيرة لها أولوية أعلى. بمجرد أن يصبح المكدس فارغًا، سينفذ Event Loop جميع المهام الصغيرة قبل الانتقال إلى المهمة الكبيرة التالية. لهذا السبب يعمل Promise.resolve().then() أسرع من setTimeout.
console.log('1');\n\nsetTimeout(() => {\n console.log('2');\n}, 0);\n\nPromise.resolve().then(() => {\n console.log('3');\n});\n\nconsole.log('4');\n\n// الإخراج: 1, 4, 3, 2\n\n\nهذا المثال كلاسيكي. setTimeout (مهمة كبيرة) يتم تأجيلها، حتى مع تأخير صفري، بينما Promise.then (مهمة صغيرة) يتم تنفيذها فورًا بعد الكود المتزامن. فهم هذا الترتيب هو مفتاح كتابة كود غير متزامن يمكن التنبؤ به.
المهام الخلفية: كيف لا تحجب الواجهة
\n\nوالآن المشكلة الرئيسية: ماذا تفعل إذا كنت بحاجة إلى تنفيذ عمل ثقيل (معالجة الصور، حسابات معقدة، تحليل البيانات)؟ إذا قمت بتشغيله في الخيط الرئيسي - ستتجمد الواجهة. الحل هو المهام الخلفية في JavaScript.
\n\nWeb Workers - تعدد خيوط حقيقي
\nWeb Workers JS تسمح بتشغيل الكود في خيط منفصل. ليس لديه وصول إلى DOM، لكن يمكنه تبادل الرسائل مع الخيط الرئيسي. هذه أداة مثالية لـ معالجة قوائم المهام JS في الخلفية.
\n\n// main.js\nconst worker = new Worker('worker.js');\n\nworker.postMessage({ data: [1, 2, 3, 4, 5, 6] });\n\nworker.onmessage = (event) => {\n console.log('النتيجة من العامل:', event.data);\n};\n\n// worker.js\nself.onmessage = (event) => {\n const numbers = event.data.data;\n // عمل ثقيل: تصفية الأرقام الزوجية\n const result = numbers.filter(n => n % 2 === 0);\n self.postMessage(result);\n};\n\n\nلاحظ: الخيط الرئيسي لا يتم حظره. يمكن للمستخدم النقر والتمرير وإدخال النص - كل شيء سيعمل بسلاسة بينما يقوم العامل بالحساب.
\n\n