Reputation: 79
I'm trying to add a delay in one of my loops but I get unexpected results. I've looked at many similar questions but since I'm trying to learn javascript I want to know why this isn't working and how I can get it to work.
If you look at the script below, shouldn't it go like this:
With output:
But the output I receive is:
(Waiting 3 seconds here)
Am I stupid or is javascript working entirely different than C++ and assembly?
var nr = 0;
const qty = 3;
function script() {
main();
console.log("Done");
}
function main() {
var cars = ["Saab", "Volvo", "BMW"];
if (nr !== qty) {
console.log(cars[nr]);
sleep();
nr++;
main();
}
else {
return;
}
}
function sleep() {
setTimeout(function () {
console.log('Waiting 3 seconds...');
return;
}, 3000);
}
<!DOCTYPE html>
<HTML>
<HEAD>
</HEAD>
<BODY>
<button onclick="script()">Run Script</button>
</BODY>
</HTML>
Upvotes: 0
Views: 191
Reputation: 13533
The setTimeout()
function doesn't block. It calls the function passed to it after the time out. You can just tell it to call main
.
function main() {
var cars = ["Saab", "Volvo", "BMW"];
if (nr !== qty) {
console.log(cars[nr]);
nr++;
sleep(3, main);
}
}
function sleep(timeout, func)
{
console.log(`Waiting ${timeout} seconds...`);
setTimeout(func, timeout * 1000);
}
Upvotes: 2
Reputation: 56
you have to learn more about asyncronous functions to better understand this issues but here is an exemple should work for you :
var nr = 0;
const qty = 3;
function script() {
const callback = ()=>{
console.log('Done')
}
main(callback)
}
async function main(cb) {
var cars = ["Saab", "Volvo", "BMW"];
if (nr !== qty){
console.log(cars[nr]);
await sleep()
nr++;
main(cb);
}else{
cb()
}
}
function sleep() {
console.log('Waiting 3 seconds...')
return new Promise((resolve)=>{
setTimeout(function () {
resolve()
}, 3000);
})
}
script()
also try to never use global object and works always with functions params
Upvotes: 1
Reputation: 979
setTimeout does not interrupt the main thread. Instead, it registers your callback function and continues executing upcoming lines.
To get your desired output, we need to have callbacks here and there. This is something called asynchronous programming in JavaScript land. You could also make use of Promise to simplify your code.
var nr = 0;
const qty = 3;
function script() {
main(function () {
console.log('Done');
});
}
function main(callback) {
var cars = ['Saab', 'Volvo', 'BMW'];
sleep(function loop() {
console.log(cars[nr++]);
if (nr === qty) {
// call the callback function
callback();
} else {
// or do the loop
sleep(loop);
}
});
}
function sleep(callback) {
setTimeout(function () {
console.log('Waiting 3 seconds...');
callback();
}, 3000);
}
Upvotes: 1
Reputation: 171
Hi bro the setTimeout doesn't block the script execution. and javascript is diffident from C++ at script execution. it's so easy with js
cars.forEach(function(value,index){
setTimeout(function(){
console.log(value);
console.log('waiting 3 s');
},index*3000)
});
Upvotes: 1
Reputation: 633
The joys of asynchronous programming.
Now's maybe a good time to head into MDN and learn about promises, and async await
async function main() {
var cars = ["Saab", "Volvo", "BMW"];
if (nr !== qty) {
console.log(cars[nr]);
await sleep();
nr++;
main();
}
else {
return;
}
}
async function sleep() {
return new Promise(resolve=>{
setTimeout(function () {
console.log('Waiting 3 seconds...');
resolve();
}, 3000);
});
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Upvotes: 2