setTimeout wait for setTimeout - javascript

I stumbled upon a problem:
the code is supposed to output "hi1" "hi2" "hi3" "hi4" in that order.
I wrote this simplified code, the actual code is more complicated and causes me to not be able to remove some of the functions I marked.
function test() {
console.log("hi2");
setTimeout(function () { //maybe replace this?
console.log("hi3");
}, 2000);
}
console.log("hi1");
test();
setTimeout(function () { //cannot get rid of this
console.log("hi4");
}, 0);
how do I make it output in order?

If you need to wait for setTimeout in your test() to execute before continuing, the easiest way is to use callback:
function test(callback) {
console.log("hi2");
setTimeout(function () {
console.log("hi3");
// Execute additional logics
callback();
}, 2000);
}
console.log("hi1");
test(function () {
setTimeout(function () {
console.log("hi4");
}, 0);
});

Use the callback or try to show your complicated code is more. We can help you to analyze it.

As others have pointed out setTimeout is asynchronous so they run in the background while the rest of the code continues. I'd guess that at the moment you get something like:
hi1
hi2
hi4
then a 2000ms delay, then
hi3
If you can't change the code much then try changing the delay for hi4 to 4000 like:
setTimeout(function () { //cannot get rid of this
console.log("hi4");
}, 4000);
That should fix the order, but it's still pretty messy and unreliable. I'd rather have something like:
function showMessage(msg, delay) {
setTimeout(function() {
console.log(msg);
}, delay);
}
showMessage('hi1', 0);
showMessage('hi2', 2000);
showMessage('hi3', 4000);
showMessage('hi4', 6000);

Related

JavaScript: best practices implementation of the setInverval function

I want to log some text to the console every n number of seconds. My code is:
function logger() {
console.log("log some stuff...");
}
setInterval(logger, 3000);
This works fine. And, the following variation works fine, too:
setInterval(
function logger() {
console.log("log some stuff...";
}, 3000);
Now, I attempt to move setInterval inside the function, as follows:
function logger() {
console.log("log some stuff...");
setInterval(logger, 3000); // moving setInterval here does NOT work
}
This does not work.
Question: Is there a way to move setInverval inside the function? And, if it is possible, is doing so recommended?
Thanks for helping out a JavaScript newbie!
### EDIT ###
Taking the suggestion from #FZs, I implemented the function as follows:
function logger(output, interval) {
var now = new Date()
setInterval(function() {
console.log(output, now.toLocaleString());
}, interval)
}
logger("Foo ", 3000)
The messages are stacking in the console because the Date is not incrementing. Is this a scope issue?
Solved as follows:
function logger(output, interval) {
setInterval(function() {
var now = new Date() // moved this line here!
console.log(output, now.toLocaleString());
}, interval)
}
logger("Foo ", 3000)

code not working when setTimeout is used

I am trying to write a code that could use voice input and based on input can migrate to another page.
My code is not waiting when timeout is used and without timeout,the code is not waiting for input.
HTML Page:
<script src="Content/SpeechRecognisation.js" type="text/javascript"></script>
<script src="Content/SpeechUtterance.js" type="text/javascript"></script>
<script src="Content/LoginScript.js" type="text/javascript"></script>
<script src="Content/Additional.js" type="text/javascript"></script>
<title>Login Screen</title>
<meta charset="utf-8" />
</head>
<body onload="Typer()"></body>
Javascript code in Js file:
function LoginPageSpeech() {
pageName = 'LoginPage';
controlPointer = "1";
var CPR_No = final_transcript;
$("#txtCPRNo").val(final_transcript);
var pageDetail = "Entered CPR Number is " + final_transcript;
CustomerResponse = final_transcript;
speak(pageDetail);
setTimeout(function(){},4000);
speak("if details are correct ,please say yes else say no after beep");
setTimeout(function () { SoundMake(); }, 4000);
setTimeout(function() {startDictation(event);},3000);
setTimeout(function() { },4000);
if (final_transcript == "YES") {
setTimeout(AuthenticationMsg,7000);
}
else
{
// setTimeout(function () { speak("Sorry.Please repeat again after beep"); }, 4000);
// setTimeout(function () { SoundMake(); }, 3000);
// setTimeout(function () { startDictation(event); }, 3000);
//
// LoginPageSpeech();
}
}
function Typer() {
pageName = "LoginPage";
speak('Welcome ,Please Speak your CPR Number after a beep');
setTimeout(function () { SoundMake(); }, 4000);
timeOutValue = 9000;
setTimeout(function () { startDictation(event); }, 4000);
}
function SoundMake() {
var snd = new Audio("data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
snd.play();
}
You use setTimeout in the wrong way. For instance, look at this part:
setTimeout(function(){},4000);
speak("if details are correct ,please say yes else say no after beep");
setTimeout(function () { SoundMake(); }, 4000);
setTimeout(function() {startDictation(event);},3000);
setTimeout(function() { },4000);
It seems like you expect the execution to halt for 4 seconds on the first line, and only then continue with the second. But that is not true. The only thing that gets delayed is the function you pass as argument to setTimeout: it will be called later. But the engine will immediately continue with the next statement. In fact, none of the functions you pass to setTimeout can execute before all the remaining code has been executed.
So... now you can see the first line of the block above is quite useless. It says: "do nothing 4 seconds from now, and now continue with the next statement".
How to fix
There are several ways, some ugly, some nice, some in between:
1. Cumulate the time to delay
Knowing that all your setTimeout calls execute at practically the same time, specify a delay that also counts for the previous delays:
setTimeout(function(){
speak("if details are correct, please say yes else say no after beep");
},4000);
setTimeout(function () { SoundMake(); }, 4000+4000);
setTimeout(function() {startDictation(event);},4000+4000+3000);
setTimeout(function() {
// ...etc
},4000+4000+3000+4000);
The downsides are:
When you change your mind on one delay you need to adapt it at several places. You could counter this by using a variable, which you increase with the next delay.
When one of the scheduled actions takes a lot of time (or the browser gets busy with other stuff), the interval between actions might get a lot smaller than expected.
2. Nest the callbacks
Here you put the next actions inside the previous callback provided to setTimeout:
setTimeout(function(){
speak("if details are correct, please say yes else say no after beep");
setTimeout(function () {
SoundMake();
setTimeout(function() {
startDictation(event);
setTimeout(function() {
// ...etc
}, 4000);
}, 3000);
}, 4000);
}, 4000);
The downside is:
The so-called "callback hell": your code can get very deeply nested, and in extreme cases your editor might show mostly white space, with your code only becoming visible if you scroll to the right. This is not practical.
3. Recursion
Here you keep invoking the same function which you call again when the next timer ticks:
(function loop(i) {
var delay = 300;
switch (i) {
case 0:
// Do nothing, just launch the setTimeout
break;
case 1:
speak("if details are correct, please say yes else say no after beep");
break;
case 2:
SoundMake();
delay = 300;
break;
case 3:
startDictation(event);
break;
default:
// etc...
return; // start no more timeout
}
setTimeout(loop.bind(null, i+1), delay);
})(0); // start with 0
The downside is:
The switch statement is a quite verbose. You could alternatively create an array of objects, where each object has the code to execute as a function property, and the delay as another property. Then you could just index that in the loop body.
4. Promises
Since ES6 there is a Promise object, which many programmers would advise using for this purpose, myself included:
// Utility to get a promise object that resolves after a given delay
function promiseDelay(delay) {
return new Promise(function (resolve) {
setTimeout(resolve, delay);
});
}
promiseDelay(400)
.then(function() {
speak("if details are correct ,please say yes else say no after beep");
return promiseDelay(4000);
}).then(function () {
SoundMake();
return promiseDelay(3000);
}).then(function () {
startDictation(event);
return promiseDelay(4000);
}).then(function () {
// etc...
});
This code is quite clean and lean.
Remarks
Note that the above tackles just part of your code. You have the same issues in the Typer function. But the principle is the same. Take your preferred solution and apply it throughout.

setInterval() will not run immediately [duplicate]

I found a solution to run interval in javascript immidiately, not waiting for a first "timeout"
setInterval(function hello() {
console.log('world');
return hello;
}(), 2500);
But problem is this solution isn't working is construction like this
(function () {
window.Banner = {
doMagic: function () {
setInterval(function magic() {
console.log('magic');
return magic;
}, 2500);
}
}
})();
Banner.doMagic();
I've tried to return Banner method, to name it and return and no success.
Point is what in real construction is much more complex, so i can't just rewrite it to "return setTimeout" solution, as offered widely, so it would be really perfect to find what am i doing wrong with this one.
http://jsfiddle.net/5jawxLnr/3/
Perhaps the most proper way to do it would be to take the whole callback outside of the setInterval call and put it in a separate variable:
(function () {
window.Banner = {
doMagic: function () {
var magic = function() {
console.log('magic');
};
setInterval(magic, 2500);
magic();
}
}
})();
Banner.doMagic();
The effect is the same as your first code, but this way your code is a little cleaner.
Your no longer self-executing the function in your 2nd code snippet. You need to change this to the following:
doMagic: function () {
setInterval(function magic() {
console.log('magic');
return magic;
}(), 2500);
}
I agree with others though, this isn't the cleanest way to do this and isn't very obvious to the next developer who comes along. I recommend storing the function in a variable, executing it immediately and then running it in the setInterval also:
doMagic: function () {
var magic = function magic() {
console.log('magic');
return magic;
}
magic();
setInterval(magic, 2500);
}
If you add the parenthesis to the below code part it does
doMagic: function () {
setInterval(function magic() {
console.log('magic');
return magic;
}(), 2500); // added them here
}
In your code there is no way to perform the required task, instead follow the below approach:
// Use function to perform the task.
function doTask () {
console.log("...");
}
// Perform task for the first time.
doTask();
// On interval do task.
setInterval(doTask, 2500);
Try this example
var hello = function() {
document.write('hello... ');
};
setInterval(hello, 1000);
hello();

Use debounce in setTimeout

I'm trying to implement debounce from underscore library within setTimeout.
setInterval(function() {
setTimeout(function(){
_.debounce(function() {
console.log('debounce');
}, 500);
}, 1000);
}, 100);
Basically, console.log('debounce') should be called once in 500ms but it seems there's no output at all in the console.
JS Bin for testing: http://jsbin.com/beqisuruwu/edit?js,output
Thanks in advance.
Are you sure you need function after setTimeout? Because _.debounce is a function itself. I am not sure either )) but code below works for me:setInterval(function() {
setTimeout(
_.debounce(function() {
console.log('debounce');
}, 500)
, 1000);
}, 100);

JavaScript setInterval immediately run

I found a solution to run interval in javascript immidiately, not waiting for a first "timeout"
setInterval(function hello() {
console.log('world');
return hello;
}(), 2500);
But problem is this solution isn't working is construction like this
(function () {
window.Banner = {
doMagic: function () {
setInterval(function magic() {
console.log('magic');
return magic;
}, 2500);
}
}
})();
Banner.doMagic();
I've tried to return Banner method, to name it and return and no success.
Point is what in real construction is much more complex, so i can't just rewrite it to "return setTimeout" solution, as offered widely, so it would be really perfect to find what am i doing wrong with this one.
http://jsfiddle.net/5jawxLnr/3/
Perhaps the most proper way to do it would be to take the whole callback outside of the setInterval call and put it in a separate variable:
(function () {
window.Banner = {
doMagic: function () {
var magic = function() {
console.log('magic');
};
setInterval(magic, 2500);
magic();
}
}
})();
Banner.doMagic();
The effect is the same as your first code, but this way your code is a little cleaner.
Your no longer self-executing the function in your 2nd code snippet. You need to change this to the following:
doMagic: function () {
setInterval(function magic() {
console.log('magic');
return magic;
}(), 2500);
}
I agree with others though, this isn't the cleanest way to do this and isn't very obvious to the next developer who comes along. I recommend storing the function in a variable, executing it immediately and then running it in the setInterval also:
doMagic: function () {
var magic = function magic() {
console.log('magic');
return magic;
}
magic();
setInterval(magic, 2500);
}
If you add the parenthesis to the below code part it does
doMagic: function () {
setInterval(function magic() {
console.log('magic');
return magic;
}(), 2500); // added them here
}
In your code there is no way to perform the required task, instead follow the below approach:
// Use function to perform the task.
function doTask () {
console.log("...");
}
// Perform task for the first time.
doTask();
// On interval do task.
setInterval(doTask, 2500);
Try this example
var hello = function() {
document.write('hello... ');
};
setInterval(hello, 1000);
hello();

Categories