הפונקציה setTimeout() בג'אווה סקריפט מבצעת פונקציה לאחר השהייה מוגדרת. היא אחת מפונקציות התזמון הנפוצות ביותר בשפה, ושימושית למשימות כמו אנימציות, פעולות מושהות, debouncing של קלט משתמש, או אירועים מתוזמנים.
במדריך זה תלמדו כיצד setTimeout() עובדת, כיצד לבטל אותה עם clearTimeout(), כיצד להעביר ארגומנטים, וכיצד להימנע מטעויות נפוצות.
setTimeout()אינה חלק משפת JavaScript עצמה. היא מסופקת על ידי ה-Web API של הדפדפן (או סביבת Node.js). הדפדפן מנהל את הטיימר ודוחף את ה-callback לתור האירועים ברגע שההשהייה פוקעת.
שימוש בסיסי ב- ()setTimeout
הפונקציה setTimeout() מקבלת שני פרמטרים: פונקציית ה-callback לביצוע וההשהייה במילישניות:
setTimeout(function, delay);הנה דוגמה:
setTimeout(function() {
console.log('This message is displayed after 2 seconds');
}, 2000);ההודעה תודפס לקונסול לאחר השהייה של 2 שניות.
ניתן גם להשתמש ב-arrow function לתחביר מקוצר יותר:
setTimeout(() => {
console.log('Arrow function after 2 seconds');
}, 2000);שימוש בפונקציות עם שם ב- ()setTimeout
במקום להעביר פונקציה אנונימית, ניתן להעביר הפניה לפונקציה עם שם:
function showMessage() {
console.log('This message is displayed after 3 seconds');
}
setTimeout(showMessage, 3000);הפונקציה showMessage מתבצעת לאחר השהייה של 3 שניות. שימו לב שמעבירים showMessage ללא סוגריים – העברת showMessage() תפעיל אותה מיד במקום לאחר ההשהייה.
העברת ארגומנטים ל- ()setTimeout
ניתן להעביר ארגומנטים נוספים ל-setTimeout() אחרי ההשהייה. הם מועברים לפונקציית ה-callback:
function greet(name, role) {
console.log(`Hello, ${name}! You are a ${role}.`);
}
setTimeout(greet, 2000, 'Alice', 'developer');לאחר 2 שניות, ייכתב לקונסול: Hello, Alice! You are a developer.
גישה זו נקייה יותר מעטיפה בפונקציה אנונימית, אם כי שתי הגישות עובדות:
// גם תקין, אבל יותר מפורט
setTimeout(() => {
greet('Alice', 'developer');
}, 2000);ביטול timeout עם ()clearTimeout
setTimeout() מחזירה מזהה מספרי שמזהה את הטיימר. ניתן להעביר מזהה זה ל-clearTimeout() כדי לבטל את הביצוע המתוזמן לפני שהוא רץ:
const timeoutID = setTimeout(() => {
console.log('This message will not be displayed');
}, 4000);
clearTimeout(timeoutID);ה-timeout מבוטל לפני שה-callback מופעל, כך שההודעה לא תודפס לעולם. שימושי למצבים כמו ביטול קריאת API ממתינה כשמשתמש עוזב את הדף, או איפוס טיימר debounce.
setTimeout עם השהייה אפס
הגדרת ההשהייה ל-0 לא מפעילה את הפונקציה מיד. היא מתזמנת את ה-callback לרוץ לאחר שה-call stack הנוכחי מתרוקן:
console.log('First');
setTimeout(() => {
console.log('Third - runs after the stack is clear');
}, 0);
console.log('Second');הפלט:
First
Second
Third - runs after the stack is clearזה קורה כי setTimeout() מציבה את ה-callback בתור המשימות (task queue), ולולאת האירועים (event loop) מעבדת אותו רק אחרי שכל הקוד הסינכרוני מסתיים. דפוס זה משמש לעיתים כדי לדחות עבודה עד שהדפדפן מסיים לרנדר.
דפדפנים מאלצים השהייה מינימלית של 4ms עבור קריאות setTimeout() מקוננות (לאחר הקינון החמישי ברצף). משמעות הדבר ש-setTimeout(fn, 0) למעשה רץ לאחר לפחות 4ms בתרחישים של קינון עמוק. לביצוע אסינכרוני מיידי אמיתי, השתמשו ב-queueMicrotask() או Promise.resolve().then() במקום.
setTimeout רקורסיבי מול setInterval
אם אתם צריכים להריץ פונקציה שוב ושוב, ייתכן שתפנו ל-setInterval(). עם זאת, setTimeout() רקורסיבי נותן לכם שליטה רבה יותר:
// שימוש ב-setInterval - מופעל כל 2 שניות ללא קשר לזמן הביצוע
const intervalID = setInterval(() => {
console.log('Interval tick');
}, 2000);
// שימוש ב-setTimeout רקורסיבי - ממתין שהביצוע יסתיים לפני תזמון הבא
function tick() {
console.log('Timeout tick');
setTimeout(tick, 2000);
}
tick();ההבדל המרכזי: setInterval() מתזמן את הקריאה הבאה מתחילת הקריאה הנוכחית, בעוד setTimeout() רקורסיבי מתזמן מסיום הקריאה. אם ה-callback דורש זמן (למשל, בקשת רשת), setTimeout() רקורסיבי מבטיח פער עקבי בין הקריאות.
כדי לעצור setTimeout() רקורסיבי, השתמשו בתנאי או שמרו את המזהה:
let count = 0;
function countUp() {
count++;
console.log(count);
if (count < 5) {
setTimeout(countUp, 1000);
}
}
countUp();טעויות נפוצות עם ()setTimeout
קריאה לפונקציה במקום העברת הפניה
זו הטעות הנפוצה ביותר. שימוש בסוגריים מפעיל את הפונקציה מיד:
// לא נכון - greet() רצה מיד, לא אחרי 2 שניות
setTimeout(greet(), 2000);
// נכון - מעביר הפניה ל-greet
setTimeout(greet, 2000);הנחה שההשהייה מדויקת
ההשהייה היא זמן המתנה מינימלי, לא טיימר מדויק. אם ה-main thread עסוק במשימות אחרות, ה-callback ימתין עד שהתהליך יתפנה:
setTimeout(() => {
console.log('This may run later than 100ms');
}, 100);
// עבודה סינכרונית כבדה חוסמת את ה-callback
for (let i = 0; i < 1000000000; i++) {}אובדן הקשר של "this"
כאשר מעבירים מתודה כ-callback, this עלול לא להצביע על האובייקט הצפוי:
const user = {
name: 'Alice',
greet() {
console.log(`Hello, ${this.name}`);
}
};
// לא נכון - "this" יהיה undefined או האובייקט הגלובלי
setTimeout(user.greet, 1000);
// תיקון 1 - עטיפה ב-arrow function
setTimeout(() => user.greet(), 1000);
// תיקון 2 - שימוש ב-bind
setTimeout(user.greet.bind(user), 1000);דוגמה חיה של ()setTimeout
הדוגמה החיה הבאה משתמשת ב-setTimeout() כדי להציג הודעה לאחר השהייה של 2 שניות כאשר לוחצים על כפתור "Start Timer". אם לוחצים על כפתור "Cancel Timer" לפני שה-timeout מסתיים, clearTimeout() עוצרת את הטיימר וההודעה "Timer canceled" מוצגת במקום.
הקוד עבור דוגמה זו:
HTML:
<button id="startButton">Start Timer</button>
<button id="cancelButton">Cancel Timer</button>
<div id="message"></div>JavaScript:
document.addEventListener('DOMContentLoaded', () => {
let timeoutID;
const messageDiv = document.getElementById('message');
const startButton = document.getElementById('startButton');
startButton.addEventListener('click', () => {
startButton.classList.add('active');
timeoutID = setTimeout(() => {
messageDiv.textContent = 'This message is displayed after 2 seconds';
startButton.classList.remove('active');
}, 2000);
});
document.getElementById('cancelButton').addEventListener('click', () => {
clearTimeout(timeoutID);
messageDiv.textContent = 'Timer canceled';
startButton.classList.remove('active');
});
});שאלות נפוצות
שאלות נפוצות על setTimeout() ב-JavaScript:
setTimeout() מבצעת פונקציה פעם אחת לאחר השהייה מוגדרת. setInterval() מבצעת פונקציה שוב ושוב בפרקי זמן קבועים עד שקוראים ל-clearInterval(). לביצוע חוזר עם שליטה רבה יותר, שקלו להשתמש ב-setTimeout() רקורסיבי במקום setInterval(), מכיוון שהוא מבטיח פער עקבי בין כל ביצוע.setTimeout() מקוננות עמוק (לאחר הרמה החמישית).setTimeout(myFunction, 2000, arg1, arg2). הארגומנטים הנוספים מועברים לפונקציית ה-callback. לחילופין, ניתן לעטוף את הקריאה ב-arrow function: setTimeout(() => myFunction(arg1, arg2), 2000).requestAnimationFrame(). למדידת זמן שחלף, השתמשו ב-performance.now() במקום להסתמך על השהיות setTimeout().setTimeout() לא מחזירה Promise, כך שלא ניתן לעשות לה await ישירות. עם זאת, ניתן לעטוף אותה ב-Promise כדי להפוך אותה ל-awaitable:function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function run() {
console.log('Start');
await delay(2000);
console.log('2 seconds later');
}סיכום
setTimeout() מתזמנת פונקציה לרוץ לאחר השהייה מוגדרת. היא מחזירה מזהה טיימר שניתן להעביר ל-clearTimeout() כדי לבטל את הביצוע לפני שהוא מופעל.
נקודות חשובות לזכור: ההשהייה היא זמן המתנה מינימלי (לא הבטחה), יש להעביר הפניות לפונקציות ללא סוגריים, והקשר this יכול ללכת לאיבוד כשמעבירים מתודות כ-callbacks. לביצוע חוזר, setTimeout() רקורסיבי עדיף לרוב על setInterval().
למדריכים נוספים על יסודות JavaScript, עיינו במדריכים על מניפולציית DOM ועל מתודות באובייקטים ו-this.

