قوائم المهام في JavaScript: اجعل موقعك أسرع وأذكى

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا موقعك "بطيء" ومن المسؤول عن ذلك

\n\n

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

\n\n

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

\n\n

كيف يعمل Event Loop: قائد أوركسترا المهام

\n\n

في قلب كل التزامن يوجد Event Loop JavaScript. هذه آلية تدور بلا نهاية وتسأل: "هل هناك شيء للتنفيذ؟ والمهام الصغيرة؟ والتقديم؟". إذا تساءلت يومًا لماذا لا يتم تنفيذ setTimeout فورًا بينما يتم تنفيذ Promise.then بشكل شبه فوري - فالإجابة تكمن هنا.

\n\n

مكدس الاستدعاءات (Call Stack)

\n

هذا هو المكان الذي تذهب إليه الدوال للتنفيذ الفوري. طالما أن المكدس مشغول، لن يحدث أي شيء آخر. إذا كانت وظيفتك تحسب مليون رقم - سيتجمد المتصفح لأن المكدس لن يتحرر.

\n\n

قائمة المهام الكبيرة (Macrotask Queue)

\n

هنا تذهب setTimeout، setInterval، أحداث DOM (النقرات، التمرير)، تحميل الموارد. يأخذ Event Loop مهمة واحدة من هذه القائمة، ينفذها، ثم يتحقق من المهام الصغيرة، ثم يعرض الصفحة - ثم يأخذ المهمة الكبيرة التالية.

\n\n

قائمة المهام الصغيرة (Microtask Queue)

\n

وهذه هي مملكة Promise، queueMicrotask، MutationObserver. المهام الصغيرة لها أولوية أعلى. بمجرد أن يصبح المكدس فارغًا، سينفذ Event Loop جميع المهام الصغيرة قبل الانتقال إلى المهمة الكبيرة التالية. لهذا السبب يعمل Promise.resolve().then() أسرع من setTimeout.

\n\n
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

المهام الخلفية: كيف لا تحجب الواجهة

\n\n

والآن المشكلة الرئيسية: ماذا تفعل إذا كنت بحاجة إلى تنفيذ عمل ثقيل (معالجة الصور، حسابات معقدة، تحليل البيانات)؟ إذا قمت بتشغيله في الخيط الرئيسي - ستتجمد الواجهة. الحل هو المهام الخلفية في JavaScript.

\n\n

Web Workers - تعدد خيوط حقيقي

\n

Web 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

setTimeout و setInterval: قائمة مهام بسيطة مع تأخير

\n<

المدونات

توصيات الكتب