Scheduling a call
- 2 methods:
-
setTimeout()
: Run a function once after the time intervalsetInterval()
: Run a function repeatedly. Starting after the time interval, and repeating with that time interval.
setTimeout()
: Run a function once after the time intervalsetInterval()
: Run a function repeatedly. Starting after the time interval, and repeating with that time interval.setInterval(() => {console.log("Tic")}, 1000) setTimeout(() => {console.log("Message 1")}, 2000); setTimeout(() => {console.log("Message 2")}, 4000); setTimeout(() => {console.log("Message 3")}, 6000);
Results: Second 1: Tic Second 2: Tic, Message 1 Second 3: Tic Second 4: Tic, Message 2 Second 5: Tic Second 6: Tic, Message 2 Second 7: Tic Second 8: Tic (until cleared)
setTimeout()
syntaxsetTimeout(function, delayMs, ...)
funcName()
, because it will run the code right away."1000"
is coerced into 1000
"1 second"
is coerced into 0function greetName(phrase, name) {...}
setTimeout(greetName, 5000, "The phrase", "The name")
clearTimeout(id)
to cancel the timer.let counter = 0; let tic = setInterval(() => { counter ++; console.log(counter); }, 1000); let underLimit = setTimeout(() => { console.log("Under limit"); }, 2147483647) let overLimit = setTimeout(() => { console.log("Over limit"); }, 2147483648); console.log(counter);
Result: 0 Over limit 1 2 3 ... // the underlimit will get executed in 24-25 days if doesn't get truncated.
function greetJello() { console.log("Hello, Jello!"); } setTimeout(greetJello, 5000); // After 5 seconds: "Hello Jello!"
function greetLater() { setTimeout(greetNow, 5000); } function greetNow() { alert("Greetings!"); } greetNow(); // Right away: "Greetings!" greetLater(); // After 5 seconds: "Greetings!"
function greetName(phrase, name) { console.log(phrase + ", " + name + "!"); } setTimeout(greetName, 5000, "Hi", "Kitty"); // After 5 seconds: "Hi, Kitty!"
setTimeout(myFunction(), 5000)
function greetJello() { console.log("Hello, Jello!"); } setTimeout(greetJello, 5000); // After 5 seconds: "Hello Jello!" setTimeout(greetJello(), 5000); // Right away: "Hello Jello!"
setTimeout
can be written with a quoted code directlysetTimeout("code", delayMS, ...)
setTimeout
needs a reference to the code, not the code directly.setTimeout(alert("Hi"), 5000)
setTimeout(myFunction(), 5000)
setTimeout("alert('Hi')", 5000)
setTimeout(myFunction, 5000)
setTimeout("alert('Hi!')", 5000); // After 5 seconds: "Hi!"
setTimeout(() => alert('Hi!'), 5000); // After 5 seconds: "Hi!"
setInterval()
setTimeout()
setInterval(function, intervalMs, ...)
setTimeout()
for further arguments and return value.setTimeout
but again and again.let counter = 0; function counterFn() { counter++; console.log(counter); } const myCounter = setInterval(counterFn, 1000); // 1 // 2 // 3 // 4 // 5 (run continuously until cleared clearInterval(myCounter); // Execution cleared
clearTimeout()
and clearInterval()
timeoutFn
from running.clearTimeout()
syntaxconst timeoutId = setTimeout(timeoutFn, ms) // return an id number, for example 1 clearTimeout(timeoutId); clearTimeout(1);
clearInterval()
syntaxconst intervalId = setInterval(intervalFn, ms) // return an id number, for example 2 clearInterval(intervalId); clearInterval(2);
setTimeout()
or setInterval()
is run, it returns an id.setTimeout()
and setInterval()
setTimeout()
is run. It gets id 1
.setInterval()
is run. it gets id 2
eventhough it's the first interval to be run, because of the same numbering pooling with timeout counterpart.const timeoutId = setTimeout(fn, ms)
const intervalId = setInterval(fn, ms)
1
, 2
, or even whatever random 6 digit number can be addressed as the constant name safely. We don't care the exact number. We refer it using the constant name.clearTimeout()
and clearInterval()
are interchangableclearTimeout()
to cancel a timeout function from running.const timeoutId = setTimeout(() => console.log("Hello!"), 5000); function stopGreeting() { clearTimeout(timeoutId); } stopGreeting(); // After 5 seconds: nothing
setTimeout()
setInterval
setInterval
let idName = setInterval(() => alert("Next alert in 2 seconds. Agree?"), 2000);
setTimeout()
let idName = setTimeout(function fnName() { alert("Next alert in 2 seconds. Agree?"); idName = setTimeout(fnName, 2000); }, 2000);
setInterval
: jammed. Alert messages have been waiting.setTimeout
: Nicely distanced 2 seconds apart from clicking.setTimeout()
let idName = setTimeout(function fnName() { let delay = prompt(`Next alert in how many seconds? Max = 5s Default = 1s`); if (delay === null) { return; } else if (!(delay >= 0 && delay <= 5)) { delay = 1; } idName = setTimeout(fnName, delay*1000); }, 1000);
let delay = 0; let reject = true; let maxDelay = 15000; let requestId = setTimeout(function request() { if (reject) { console.log(`Request rejected. Last waiting time: ${delay/1000} s.`) if (delay < maxDelay) { delay = delay + 5000; console.log(`Resend request in ${delay/1000} s.`); let counter = 0; let counterId = setInterval(() => { counter ++; console.log(counter); }, 1000) let stopCount = setTimeout(() => { clearInterval(counterId); }, delay) requestId = setTimeout(request, delay); } else { console.log(`Max waiting time ${maxDelay/1000} s. Request cancelled. `); clearTimeout(requestId); } } else { console.log("Request fulfilled. Request function is stopped."); clearTimeout(requestId); } }, delay);
reject = false;
maxDelay = 10000;
let nestLimit = setTimeout(function hi() { console.log(`Hi`); nestLimit = setTimeout(hi()) }) let intLimit = setInterval(function hi() { console.log(`Hi`); })
Nested setTimeout // (10296) Hi // Uncaught RangeError: Maximum call stack size exceeded Regular setInterval // (100K) Hi // ... and still going
setTimeout
, setInterval
, clearTimeout
, clearInterval
<div> <label for="timeInput2">Enter time (0-60 seconds): </label> <input type="text" id="timeInput2" value="3" size="2"> <input type="submit" id="timerButton2" value="Start timer"> </div> <p id="timerPar" style="display: none;"></p> <p id="counterPar" style="display: none;"></p> <p id="ringerPar" style="display: none;">Ring Ring Ring!</p> <div id="cancelBox" style="display: none"> <input type="submit" id="cancelButton" value="Cancel timer"> </div> <p id="cancelComment" style="display: none;">Timer cancelled.</p> <div id="refreshBox" style="display: none"> <input type="submit" id="refreshButton" value="Refresh timer"> </div>
let myTimer; let myInterval; function timerFunction2() { refreshTimer(); const timeLimit2 = document.getElementById("timeInput2").value; if (timeLimit2 >= 0 && timeLimit2 <= 60) { let counterText = ""; let counter = 0; document.getElementById("timerButton2").disabled = true; document.getElementById("timerPar").textContent = `Timer is set for ${timeLimit2} seconds.`; document.getElementById("timerPar").style.display = "block"; document.getElementById("counterPar").textContent = counterText; document.getElementById("counterPar").style.display = "block"; document.getElementById("cancelBox").style.display = "block"; myInterval = setInterval(() => { counter ++; counterText += `${counter} `; document.getElementById("counterPar").textContent = counterText; }, 1000) myTimer = setTimeout(() => { clearInterval(myInterval); document.getElementById("ringerPar").style.display = "block"; document.getElementById("cancelBox").style.display = "none"; document.getElementById("refreshBox").style.display = "block"; document.getElementById("timerButton2").disabled = false; }, timeLimit2*1000); } } function cancelTimer() { clearTimeout(myTimer); clearInterval(myInterval); document.getElementById("cancelBox").style.display = "none"; document.getElementById("cancelComment").style.display = "block"; document.getElementById("refreshBox").style.display = "block"; document.getElementById("timerButton2").disabled = false; } function refreshTimer() { document.getElementById("counterPar").textContent = ""; document.getElementById("timerPar").textContent = ""; document.getElementById("cancelBox").style.display = "none"; document.getElementById("refreshBox").style.display = "none"; document.getElementById("timerPar").style.display = "none"; document.getElementById("counterPar").style.display = "none"; document.getElementById("cancelComment").style.display = "none"; document.getElementById("ringerPar").style.display = "none"; document.getElementById("timerButton2").disabled = false; } document.getElementById("timerButton2").addEventListener("click", timerFunction2); document.getElementById("cancelButton").addEventListener("click", cancelTimer); document.getElementById("refreshButton").addEventListener("click", refreshTimer);
setTimeout(fn)
setTimeout(() => console.log("Timeout with 0 delay"));
setInterval(fn)
clearInterval(id)
let intZero = setInterval(() => { console.log("Interval with 0 delay. Terminate: clearInterval(intZero)"); });
setInterval(fn)
with auto-termination: internal counterlet counter = 0; let intZeroCount = setInterval(() => { counter ++; console.log("Interval with 0 delay. Auto-termination at 1000th run."); if (counter === 1000) { clearInterval(intZeroCount); } });
setInterval(fn)
with auto-termination: external setTimeout
let intZeroTimed = setInterval(() => { console.log("Interval with 0 delay. Auto-termination at 2s with external setTimeout"); }); setTimeout(() => { clearInterval(intZeroTimed); }, 2000)
setImmediate
for Node.js
let start = Date.now(); let counter = 0; let timeoutArray = []; setTimeout(function check() { timeoutArray.push(Date.now() - start); start = Date.now(); counter ++; if (counter < 20) {setTimeout(check)} }); timeoutArray; // (20) [2, 1, 1, 1, 4, 4, 5, 4, 4, 4, 5, 4, 4, 4, 5, 4, 4, 4, 5, 4]
let start = Date.now(); let counter = 0; let intervalArray = []; let intCheck = setInterval(function check() { intervalArray.push(Date.now() - start); counter ++; if (counter === 20) {clearInterval(intCheck)} }); intervalArray; // (20) [2, 0, 1, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
setTimeout
and setInterval
invocations are after the current script execution is finished.setTimeout
and setInterval
are written first, it will have to wait the codes after to run.setTimeout(() => alert("Timeout")); alert("Current script");
setTimeout
and setInterval
are written first but run last.// Code 1: setTimeout setTimeout(() => console.log("Code 1: Timeout set at 5000."),5000); // Code 2: setInterval counter = 0; let intervalId = setInterval(() => { counter++; console.log("Code 2: Interval " + counter); if (counter === 10) { clearInterval(intervalId); } }, 1000) // Code 3: plain console log console.log("Code 3: Plain console log run."); // Code 4: for-loop and result let i = 1; for(i; i <= 1000; i++) { i *= i }; console.log("Code 4: For-loop multiplication = " + i); //Code 5: function function multiply(a, b) { return a*b; } console.log("Code 5: function multiply = " + multiply(100, 100))
Code 3: Plain console log run.
Code 4: For-loop multiplication = 458330
Code 5: function multiply = 10000
Code 2: Interval 1
Code 2: Interval 2
Code 2: Interval 3
Code 2: Interval 4
Code 1: Timeout set at 5000.
Code 2: Interval 5
Code 2: Interval 6
Code 2: Interval 7
Code 2: Interval 8
Code 2: Interval 9
Code 2: Interval 10
setTimeout
outside function, inside function, and function without timeoutsetTimeout("console.log('Timeout outside function')", 5000); function funcTimey() { setTimeout("console.log('Function with timeout inside')", 5000) }; funcTimey(); function funcLoggy() { console.log('Function without timeout') }; funcLoggy();
// Immediately Function without timeout // The same time, after 5 seconds: Timeout outside function Function with timeout inside
<div> <input type="button" id="startCounter" value="Start counting"> <input type="button" id="stopCounter" value="Stop counting"> <input type="button" id="backToZero" value="Back to Zero"> </div> <div id="counterBox" size="5" style="font-size:2rem; color: pink;">0</div>
let coolCounter; let number = 0; let counterOn = false; function startCount() { if (!counterOn) { coolCounter = setInterval(() => { number ++; document.getElementById("counterBox").textContent = number; }, 1000) } counterOn = true; } function stopCount() { clearInterval(coolCounter); counterOn = false; } function zeroNumber() { clearInterval(coolCounter); counterOn = false; number = 0; document.getElementById("counterBox").textContent = number; } document.getElementById("startCounter").addEventListener("click", startCount); document.getElementById("stopCounter").addEventListener("click", stopCount); document.getElementById("backToZero").addEventListener("click", zeroNumber);
<div class="calendar"> <span id="currentDay" style="margin: auto;"></span> </div> <div class="calendar"> <span id="currentDate"></span> <span id="currentMonth"></span> <span id="currentYear"></span> </div> <div class="calendar"> <span id="currentHour"></span> : <span id="currentMinute"></span> : <span id="currentSecond"></span> </div>
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; function getName (array, index) { return array[index]; } Alternative 1: Direct HTML element assignments function updateDisplay1() { const timeStamp = new Date(); document.getElementById("currentSecond").textContent = timeStamp.getSeconds(); document.getElementById("currentMinute").textContent = timeStamp.getMinutes(); document.getElementById("currentHour").textContent = timeStamp.getHours(); document.getElementById("currentDate").textContent = timeStamp.getDate(); document.getElementById("currentMonth").textContent = getName(months, timeStamp.getMonth()); document.getElementById("currentYear").textContent = timeStamp.getFullYear(); document.getElementById("currentDay").textContent = getName(days, timeStamp.getDay()); } updateDisplay1(); setInterval(updateDisplay1, 1000); Alternative 2: HTML element assignments through array const calendarDisplay = [ { id: "currentSecond", content: (timeStamp) => timeStamp.getSeconds()}, { id: "currentMinute", content: (timeStamp) => timeStamp.getMinutes()}, { id: "currentHour", content: (timeStamp) => timeStamp.getHours()}, { id: "currentDate", content: (timeStamp) => timeStamp.getDate()}, { id: "currentMonth", content: (timeStamp) => getName(months, timeStamp.getMonth())}, { id: "currentYear", content: (timeStamp) => timeStamp.getFullYear()}, { id: "currentDay", content: (timeStamp) => getName(days, timeStamp.getDay())}, ] function updateDisplay2() { const timeStamp = new Date(); calendarDisplay.forEach(element => { document.getElementById(element.id).textContent = element.content(timeStamp); }) } updateDisplay2(); setInterval(updateDisplay2, 1000);
printNumber(from, to)
from
ending with to
function printNumbers(from, to) { let interId = setInterval(() => { console.log(from); from++; if (from > to) { clearInterval(interId); } }, 1000) };
printNumbers(154647, 154651); 154647 154648 154649 154650 154651
this
contextsetTimeout()
is called from an execution context separate from the function from which setTimeout
was called.this
keyword mut be set in the call or with bind
, ot it will default to the window
(or global
) object. It will not be the same as the this
value for function that called setTimeout
thisArg
like in array methods like forEach()
and reduce().
this
in usual situationconst students = ['Abe', 'Ben', 'Che']; students.printName = function (el) { console.log(arguments.length > 0 ? this[el] : this); }; students.printName(); // (3) ['Abe', 'Ben', 'Che', printName: ƒ] students.printName(0); // Abe
this
in setTimeout
setTimeout(students.printName, 1000); setTimeout(students.printName, 2000, 0); setTimeout(students.printName, 3000, "0");
After 1 second: object Window {window: Window, ... After 2 seconds: undefined After 3 seconds: undefined
this
is not set, so the default (window) is used.alert
box because in Javascript, there's a priority for alert box over HTML manipulation. Resulting in the last counter result didn't appear in the paragraph, despite counter coded prior to alert. To force alert to wait, we are going to use promise
method.
setInterval
is finished.Promise
setTimeout
setInterval
clearTimeout
clearInterval