مقدمة: لماذا لا يوجد sleep() طبيعي في JavaScript؟
\nمرحبًا، زملائي المطورين! إذا كنت قد انتقلت يومًا إلى JavaScript من Python أو PHP أو Java، فبالتأكيد تساءلت: "أين هو sleep(1) المفضل لدي، لكي ينام البرنامج لمدة ثانية؟". وبعد البحث في الوثائق، تكتشف بدهشة أن هذه الدالة غير موجودة في JS الخالص.
هذا ليس خطأ، بل ميزة. JavaScript هي لغة أحادية الخيط تعمل في حلقة الأحداث (Event Loop). إذا قمنا ببساطة بحظر الخيط لمدة ثانية، فسيتجمد معه الواجهة بأكملها، ولن تتم معالجة النقرات والرسوم المتحركة والطلبات. sleep() الحاجب هو نمط معادٍ للويب.
لكن هذا لا يعني أننا لا نستطيع التوقف مؤقتًا. سؤال "ما هو إصدار JavaScript من sleep()؟" على Stack Overflow حصد مئات الآلاف من المشاهدات، وفي عام 2025 لدينا ترسانة كاملة من الحلول - من البسيطة إلى المعقدة.
\nفي هذه المقالة (خاصة بالبوابة التعليمية pythonlib.ru) سنستعرض جميع الطرق القانونية لجعل JavaScript ينام، إيجابياتها وسلبياتها، وسنحدد أفضل الممارسات للمواقف المختلفة.
\n\nالطريقة الأصح: async/await والوعود (Promises)
\nبدءًا من ES2017، ظهرت في JavaScript البرمجة غير المتزامنة المعززة - async/await. إذا كنت تريد التوقف مؤقتًا دون حظر الخيط الرئيسي، فأنت بحاجة إلى دالة تُرجع Promise يتم حله بعد الوقت المطلوب.
ها هي، دالة sleep() المخصصة لدينا لعام 2025:
// دالة تأخير عالمية\nfunction sleep(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n// الاستخدام\nasync function demo() {\n console.log('نبدأ...');\n await sleep(2000); // انتظار لمدة ثانيتين\n console.log('مرت ثانيتان!');\n}\n\ndemo();\n\n\nهذا هو sleep غير الحاجب. أثناء تنفيذ await sleep(2000)، يستمر باقي الكود (معالجات الأحداث، الدوال غير المتزامنة الأخرى) في العمل. حلقة الأحداث لا تنام - إنها فقط تؤجل تنفيذ الأسطر التالية حتى يتم حل الوعد.
لماذا هذه أفضل ممارسة؟
\n- \n
- لا يحجب واجهة المستخدم - تظل الواجهة سريعة الاستجابة. \n
- صيغة قياسية - تُقرأ ككود متزامن عادي. \n
- مناسب لـ Node.js - الخادم لا يتجمد. \n
- مدعوم في كل مكان - المتصفحات الحديثة و Node.js 8+. \n
setTimeout() الجيد القديم
\nقبل عصر async/await، كنا نستخدم setTimeout(). لا يزال حيًا وملائمًا، لكنه يتطلب دوال استرجاع (callbacks)، مما يولد "جحيم دوال الاسترجاع".
console.log('بداية');\nsetTimeout(() => {\n console.log('مرت 1.5 ثانية');\n}, 1500);\nconsole.log('نهاية (ستُنفذ فورًا)');\n\n\nسيكون الإخراج في وحدة التحكم: بداية، ثم نهاية (فوريًا)، وبعد ذلك فقط مرت 1.5 ثانية. هذا ليس بالضبط sleep() بالمعنى الكلاسيكي، لكنه مثالي للسيناريوهات البسيطة.
متى نستخدم setTimeout؟
\n- \n
- عند الحاجة لتنفيذ إجراء مرة واحدة بعد فترة زمنية معينة. \n
- في الرسوم المتحركة (مثل تشغيل تأثير بعد 300 مللي ثانية). \n
- في البرامج النصية البسيطة دون منطق معقد. \n
sleep الحاجب (ولماذا لا يجب فعله)
\nنعم، تقنيًا يمكنك تجميد الخيط باستخدام حلقة فارغة. لكن هذا شر محض.
\n\nfunction blockSleep(milliseconds) {\n const start = Date.now();\n while (Date.now() - start < milliseconds) {\n // فارغ - المعالج يسخن، والعلامة التبويبية تتجمد\n }\n}\n\nconsole.log('بداية');\nblockSleep(3000);\nconsole.log('مرت 3 ثوانٍ (لكن المتصفح تجمد)');\n\n\nهذا الكود يفعل بالضبط ما تطلبه: يوقف التنفيذ