شرح setTimeout() في JavaScript: تأخير تنفيذ الكود لعدد من الثواني
ما هي الدالة setTimeout() في JavaScript؟
إذا كنت ترغب في تأخير تنفيذ جزء من الشيفرة البرمجية لعدة ثوانٍ، فإن الدالة setTimeout() تُعد من أهم الأدوات المتاحة في JavaScript. وظيفتها الأساسية هي جدولة تنفيذ دالة معيّنة بعد مرور مدة زمنية تحددها أنت مسبقاً.
تُستخدم هذه الدالة بكثرة في تطوير واجهات المستخدم، وعرض الرسائل المؤقتة، وتشغيل التأثيرات البصرية، وإدارة بعض خطوات التفاعل داخل التطبيقات والمواقع.

صيغة استخدام setTimeout()
الصيغة العامة للدالة تأتي بالشكل التالي:
let timeoutID = setTimeout(function, delayInMilliseconds, argument1, argument2, ...);
ويتكوّن هذا الاستدعاء من العناصر التالية:
function: الدالة التي سيتم تنفيذها بعد انتهاء المدة.delayInMilliseconds: مدة الانتظار بوحدة المللي ثانية.argument1وargument2: معاملات اختيارية يمكن تمريرها إلى الدالة.timeoutID: معرّف فريد يعيدهsetTimeout()ويمكن استخدامه لاحقاً لإلغاء المؤقت.
من المهم الانتباه إلى أن كل 1000 مللي ثانية تساوي ثانية واحدة.
كيفية تأخير تنفيذ رسالة لثلاث ثوانٍ
في المثال التالي سيتم عرض رسالة داخل الصفحة بعد مرور 3 ثوانٍ:
const para = document.getElementById("para");
function myMessage() {
para.innerHTML = "I just appeared";
console.log("message appeared");
}
setTimeout(myMessage, 3000);
هنا قمنا بتمرير الدالة myMessage إلى setTimeout() مع قيمة تأخير مقدارها 3000 مللي ثانية، لذلك لن تُنفذ الدالة إلا بعد انتهاء هذه المدة.
ماذا يحدث إذا لم تحدد مدة التأخير؟
عند عدم تمرير قيمة التأخير إلى setTimeout()، فإن المتصفح يتعامل معها عملياً على أنها 0. وهذا يعني أن الدالة ستُجدول للتنفيذ مباشرة بعد انتهاء دورة التنفيذ الحالية.
const para = document.getElementById("para");
function myMessage() {
para.innerHTML = "No delay in this message";
console.log("message appeared immediately");
}
setTimeout(myMessage);
ورغم أن التنفيذ يبدو فورياً، إلا أنه يظل خاضعاً لآلية جدولة المهام داخل محرك JavaScript، وليس تنفيذاً متزامناً داخل نفس السطر.
تمرير معاملات إلى الدالة داخل setTimeout()
يمكنك إرسال معاملات اختيارية إلى الدالة التي سيتم تنفيذها لاحقاً. هذه الميزة مفيدة عندما تريد استخدام نفس الدالة مع بيانات مختلفة دون إنشاء دوال إضافية.
const ashley = document.getElementById("ashley");
function lunchMenu(food1, food2) {
ashley.innerHTML = `<strong>Ashley: </strong>I had ${food1} and ${food2}.`;
}
setTimeout(lunchMenu, 3000, "pizza", "salad");
في هذا المثال، سيتم استدعاء الدالة lunchMenu بعد 3 ثوانٍ، مع تمرير القيمتين "pizza" و"salad" كوسيطين.
ما هو timeoutID ولماذا تحتاج إليه؟
كل استدعاء للدالة setTimeout() يُرجع قيمة رقمية فريدة تُخزن غالباً في متغير مثل timeoutID. هذه القيمة تُمثل معرّف المؤقت، وتُستخدم عندما تريد إيقاف المؤقت قبل أن ينفذ الدالة.
وجود هذا المعرّف مهم في التطبيقات التفاعلية، مثل النوافذ المنبثقة، والرسائل المؤقتة، والتأخيرات التي يمكن للمستخدم إلغاؤها.
إلغاء المؤقت باستخدام clearTimeout()
إذا احتجت إلى منع تنفيذ الدالة المجدولة، فيمكنك استخدام clearTimeout(). كل ما عليك هو تمرير قيمة timeoutID التي حصلت عليها عند إنشاء المؤقت.
clearTimeout(timeoutID);
يوضح المثال التالي فكرة إلغاء المؤقت عند ضغط المستخدم على زر إيقاف:
const timerMsg = document.getElementById("message1");
const stopBtn = document.getElementById("stop");
function timerMessage() {
timerMsg.innerHTML = "Thanks for waiting!";
}
let timeoutID = setTimeout(timerMessage, 10000);
stopBtn.addEventListener("click", () => {
clearTimeout(timeoutID);
timerMsg.innerHTML = "Timer was stopped";
});
في هذا السيناريو، تم ضبط المؤقت ليعرض رسالة بعد 10 ثوانٍ. لكن إذا ضغط المستخدم على الزر قبل انتهاء المدة، يتم إلغاء المؤقت ولن تظهر الرسالة الأصلية.
لماذا يجب تجنب تمرير نص إلى setTimeout()؟
من الأخطاء الشائعة تمرير سلسلة نصية بدلاً من دالة. ورغم أن هذا الأسلوب قد يعمل في بعض البيئات، فإنه يُعد ممارسة سيئة ومصدر خطر أمني، لأنه يشبه سلوك eval الضمني.
هذا مثال غير مستحب:
setTimeout("console.log('Do not do this');", 1000);

والأسلوب الصحيح هو تمرير دالة صريحة أو دالة سهمية:
setTimeout(function() {
console.log("Do this instead");
}, 1000);
هذا النهج أوضح، وأكثر أماناً، وأسهل في التتبع والصيانة داخل المشاريع الكبيرة.
الفرق بين setTimeout() وsetInterval()
على الرغم من التشابه بين الدالتين، فإن بينهما فرقاً جوهرياً:
setTimeout(): تنفذ الدالة مرة واحدة فقط بعد مرور مدة محددة.setInterval(): تنفذ الدالة بشكل متكرر كلما انقضت المدة المحددة.
بمعنى آخر، إذا كنت تريد تنفيذ مهمة لمرة واحدة بعد تأخير، فاستخدم setTimeout(). أما إذا أردت تكرار مهمة بشكل دوري، فاستخدم setInterval().
صيغة setInterval()
let intervalID = setInterval(function, delayInMilliseconds, argument1, argument2, ...);
مثال على تنفيذ متكرر كل ثانية
let intervalID = setInterval(() => {
salesMsg.innerHTML += "<p>Sale ends soon. BUY NOW!</p>";
}, 1000);
في هذا المثال، ستُضاف رسالة إلى الشاشة كل ثانية بشكل متكرر.
إيقاف التكرار باستخدام clearInterval()
لإيقاف المؤقت المتكرر، نستخدم الدالة clearInterval() مع المعرّف intervalID:
setTimeout(() => {
clearInterval(intervalID);
}, 10000);
هنا تم استخدام setTimeout() لإيقاف setInterval() بعد مرور 10 ثوانٍ، وهي طريقة عملية شائعة عند بناء الرسوم المتحركة أو الرسائل الترويجية المؤقتة.
أمثلة عملية من مشاريع حقيقية
لا تقتصر استخدامات setTimeout() وsetInterval() على الأمثلة التعليمية البسيطة، بل تدخل في عدد كبير من السيناريوهات العملية داخل المواقع والتطبيقات.
تشغيل شريط تقدم بعد تحميل الصفحة
في المثال التالي يبدأ شريط التقدم بعد ثانيتين من تحميل الصفحة. وبعد ذلك يتم تشغيل دالة animate() بشكل متكرر إلى أن يصل العرض إلى 100%.
setTimeout(() => {
let intervalID = setInterval(() => {
if (barWidth === 100) {
clearInterval(intervalID);
} else {
animate();
}
}, 100); // this sets the speed of the animation
}, 2000);
هذا المثال يوضح كيف يمكن دمج setTimeout() مع setInterval() لتحقيق سلوك ديناميكي أكثر مرونة.
تحديث رسالة الإنجاز عند اكتمال الشريط
const animate = () => {
barWidth++;
progressBar.style.width = `${barWidth}%`;
setTimeout(() => {
loadingMsg.innerHTML = `${barWidth}% Completed`;
}, 10100);
};
داخل الدالة animate() يتم تحديث عرض الشريط أولاً، ثم جدولة تحديث النص المعروض للمستخدم. هذه الفكرة شائعة في واجهات التحميل، وشاشات الانتظار، وتجارب المستخدم التفاعلية.
متى تستخدم مؤقتات JavaScript في تطوير الواجهات؟
يمكن الاستفادة من المؤقتات في عدد واسع من الحالات، مثل:
- عرض رسائل التنبيه أو النجاح بعد مدة قصيرة.
- إخفاء العناصر المؤقتة تلقائياً.
- بناء مؤثرات بصرية وحركات بسيطة.
- تشغيل أحداث متسلسلة داخل الألعاب والمتصفحات التفاعلية.
- إدارة فترات الانتظار بين الطلبات أو العمليات غير المتزامنة.
لكن يُنصح دائماً بعدم الإفراط في استخدامها، خصوصاً عندما تكون هناك بدائل أكثر دقة تعتمد على الأحداث الفعلية أو الوعود Promises أو البرمجة غير المتزامنة الحديثة.
أفضل الممارسات عند استخدام setTimeout()
- مرر دالة دائماً، ولا تستخدم سلسلة نصية.
- احفظ قيمة
timeoutIDإذا كنت تتوقع الحاجة إلى إلغاء المؤقت لاحقاً. - استخدم أسماء واضحة للدوال مثل
showMessageأوstartAnimation. - احرص على أن تكون مدة التأخير منطقية ولا تضر بتجربة المستخدم.
- لا تعتمد على المؤقتات وحدها في تنفيذ المنطق الحساس زمنياً، لأن سلوك التنفيذ قد يتأثر بضغط المتصفح أو تبويب الخلفية.
الخلاصة التقنية
تُعد الدالة setTimeout() من الأدوات الأساسية في JavaScript لتأخير تنفيذ الشيفرة لمرة واحدة، بينما تُستخدم setInterval() للتنفيذ المتكرر على فترات منتظمة. الفهم الصحيح للفرق بينهما، ومعرفة كيفية استخدام clearTimeout() وclearInterval()، يمنحك قدرة أفضل على بناء واجهات أكثر تفاعلاً وتنظيماً. ومن الناحية التقنية، فإن الاستخدام الآمن والواضح للمؤقتات يرفع جودة الشيفرة ويحسن قابلية صيانتها، خاصة في المشاريع التي تعتمد على تجربة مستخدم سلسة ومدروسة.