| الدالة | الوظيفة | الإلغاء |
|---|---|---|
| setTimeout() | تنفيذ مرة واحدة بعد تأخير | clearTimeout() |
| setInterval() | تنفيذ متكرر كل فترة | clearInterval() |
| requestAnimationFrame() | تنفيذ متزامن مع تحديث الشاشة | cancelAnimationFrame() |
setTimeout() تُجدول تنفيذ دالة مرة واحدة فقط بعد مرور فترة زمنية محددة بالمللي ثانية (1000 مللي ثانية = ثانية واحدة). تقبل الدالة وسيطين أساسيين: الدالة المراد تنفيذها، والوقت بالمللي ثانية، مع إمكانية تمرير وسائط إضافية تُمرَّر بدورها للدالة عند تنفيذها. مهم جداً تذكّر أن الوقت الممرَّر هو "الحد الأدنى" للانتظار وليس ضماناً دقيقاً — كما تعلمنا في الـ Event Loop، الدالة تنتظر أيضاً حتى يفرغ مكدس الاستدعاء من أي كود متزامن قيد التنفيذ.
setInterval() مشابهة لكنها تُكرر تنفيذ الدالة باستمرار كل فترة زمنية محددة، دون توقف، حتى تُلغيها صراحة. هذا يجعلها مثالية لمهام مثل الساعات الرقمية، العدادات التنازلية، أو تحديث بيانات دورياً من خادم.
لإلغاء مؤقت مُجدوَل قبل تنفيذه (لـ setTimeout) أو إيقاف تكراره (لـ setInterval)، تحتاج أولاً تخزين القيمة التي تُعيدها الدالة عند استدعائها (وهي معرّف رقمي فريد للمؤقت)، ثم تمرير هذا المعرّف لدالة clearTimeout() أو clearInterval() على التوالي. نسيان إلغاء setInterval عندما لا تعود بحاجته يُعتبر خطأ شائعاً جداً يُسبب تسرب ذاكرة (Memory Leak) واستمرار تنفيذ كود غير مرغوب فيه حتى بعد مغادرة المستخدم للصفحة أو المكوّن المعني.
في التطبيقات الحديثة، يُفضَّل غالباً استخدام requestAnimationFrame() بدلاً من setInterval عند التعامل مع الرسوم المتحركة (Animations) تحديداً، لأنه متزامن مع معدل تحديث شاشة المتصفح (عادة 60 إطاراً في الثانية) مما يُنتج حركة أكثر سلاسة ويوفر البطارية عند عدم ظهور علامة التبويب.
| 1 | const معرف_المؤقت = setTimeout(() => { |
| 2 | console.log("مرت 3 ثوانٍ"); |
| 3 | }, 3000); |
| 4 | |
| 5 | clearTimeout(معرف_المؤقت); // إلغاء قبل التنفيذ |
| 6 | |
| 7 | const معرف_الفاصل = setInterval(() => { |
| 8 | console.log("تكرار كل ثانية"); |
| 9 | }, 1000); |
| 10 | |
| 11 | clearInterval(معرف_الفاصل); // إيقاف التكرار |
مثال 1: عداد تنازلي كامل مع الإيقاف الصحيح
| 1 | // عداد تنازلي حقيقي باستخدام setInterval |
| 2 | function بدء_العد_التنازلي(من) { |
| 3 | let ثواني_متبقية = من; |
| 4 | const المؤقت = setInterval(() => { |
| 5 | console.log(ثواني_متبقية); |
| 6 | ثواني_متبقية--; |
| 7 | |
| 8 | if (ثواني_متبقية < 0) { |
| 9 | clearInterval(المؤقت); // مهم جداً: إيقاف التكرار عند الانتهاء |
| 10 | console.log("انتهى الوقت!"); |
| 11 | } |
| 12 | }, 1000); |
| 13 | } |
| 14 | بدء_العد_التنازلي(5); |
مثال 2: نمط Debounce الشهير مبني على setTimeout
| 1 | // Debounce: تأخير تنفيذ دالة حتى يتوقف المستخدم عن الكتابة |
| 2 | function تأخير_البحث(دالة, تأخير) { |
| 3 | let مؤقت; |
| 4 | return function (...أوسطة) { |
| 5 | clearTimeout(مؤقت); // إلغاء المؤقت السابق مع كل ضغطة |
| 6 | مؤقت = setTimeout(() => دالة(...أوسطة), تأخير); |
| 7 | }; |
| 8 | } |
| 9 | |
| 10 | const بحث_مؤجل = تأخير_البحث(كلمة => console.log("بحث عن:", كلمة), 500); |
| 11 | // استخدام: مربع_نص.addEventListener("input", e => بحث_مؤجل(e.target.value)); |