Why do two of the three functions not delay? - javascript

I have 3 settimeout functions in one function.
The one calling the fades() works fine, not the one with the comments surrounded.
This is what I wanted it to do: first, play the loading bar. Next, fade the bar out and show a button.
The load bar didn't quite work but after that a button should have toggle_visibility(), which would show it.
<script>
function toggle_visibility(id) {
var e = document.getElementById(id);
if (e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
};
function fades() {
//problem settimeout
setTimeout(function(){
$('#button1').toggle_visibility();
}, 5500);
// end of problem
setTimeout(function() {
playDemo('disney', 2, disneyInterval);
}, 1000);
setTimeout(function() {
$('#mydiv').fadeOut();
}, 5000);
};
setTimeout(function() {
fades();
}, 10);
</script>

$('#button1').toggle_visibility();
This code means function toggle_visibility is a function of jQuery. But in your code, it is just a function.
You can invoke it like toggle_visibility('button1'). This will change button1's display once.

toggle_visibility(button1)
"toggle_visibility" is not a function for jquery! so $().toggle_visibility is undefined

1) To verify whether your callback function is being called or not, you simply place a console.log inside it with something like "function XXX called".
2) The timing in setTimeout is not perfect. It guarantees that your function will not be called before that time you specified has passed but does NOT guarantee it to be exactly at the requested time.
So if you just say:
setTimeout(f2, 500);
setTimeout(f3, 600);
It does not guarantee that f3 will be called exactly 100ms after f2.
If you try to rely on this to run animations, they will not always be smooth.
If you need to "chain" calls, let each callback call the other.
setTimeout(function() {
console.log("Function 1");
// do stuff
setTimeout(function() {
console.log("Function 2");
// do stuff
setTimeout(function() {
console.log("Function 3")
// do stuff
},0);
}, 500);
}, 1000)
Nested callbacks are nasty to read/write though, so you can flatten it out
function f1() {
console.log("Function 1");
// do stuff
setTimeout(f2, 500)
}
function f2() {
console.log("Function 2");
// do stuff
setTimeout(f3, 1000)
}
function f3() {
console.log("Function 3")
// do stuff
}
setTimeout(f1, 1000)

That's right guys. As was said before, here what you can do - implement this function to jQuery:
function toggle_visibility(id) {
var e = $('#'+id);
if (e.css('display') == 'block'){
e.css('display', 'none');
}
else {
e.css('display', 'block');
}
}
jQuery.fn.toggle_visibility = function() {
return toggle_visibility(this.attr('id'));
}
Now you can use it like you used)

Related

Call a function max once in a sec

I have a function that is used to send messages and that is called multiple times in a sec.
But I want to call that function once a sec and delay other calls of that function with another 1-second of the previous call.
So that only that function run in the background and called once in a second, no matters how many times it is called it will delay each call to one second ahead.
For example:
function foo(a) {
console.log(a)
}
foo('one');
foo('two');
foo('three');
in the above example, foo is called three times within a sec but I want to have it called like after the 1 second it should return "one" after 2 seconds it should return 'second' and so on and it should be asynchronous.
How can I do this?
The technology I am using is Javascript.
Thanks
Well this is the first thing I came up with - perhaps it's crude.
var queuedUpCalls = [];
var currentlyProcessingCall = false;
function foo(a) {
if (currentlyProcessingCall) {
queuedUpCalls.push(a);
return;
}
currentlyProcessingCall = true;
setTimeout(function(){
console.log(a);
currentlyProcessingCall = false;
if (queuedUpCalls.length) {
var nextCallArg = queuedUpCalls.shift();
foo(nextCallArg);
}
},1000);
}
foo('one');
foo('two');
foo('three');
For each call, if you're not currently processing a call, just call setTimeout with a delay of 1000ms. If you are processing a call, save off the argument, and when the setTimeout that you kicked off finishes, process it.
Somewhat improved answer using setInterval:
var queuedUpCalls = [];
var timerId;
function foo(a) {
queuedUpCalls.push(a);
if (timerId) {
return;
}
timerId = setInterval(function(){
if (!queuedUpCalls.length) {
clearInterval(timerId);
timerId = null;
return;
}
var nextCallArg = queuedUpCalls.shift();
console.log(nextCallArg);
}, 1000);
}
foo('one');
foo('two');
foo('three');
Here is a simple queue system, it basically just pushes the functions onto an array, and then splice's them off every second.
const queue = [];
setInterval(function () {
if (!queue.length) return;
const f = queue[0];
queue.splice(0, 1);
f();
}, 1000);
function foo(a) {
queue.push(function () {
console.log(a)
});
}
foo('one');
foo('two');
foo('three');
you could use this to run the main code first and then run some more code a little later.
function firstfunction() {
alert('I am ran first');
setTimeout(function(){ alert('I am ran 3 seconds later') }, 3000);
}
<button onclick="firstfunction();">click me</button>
function foo(a)
{
if (typeof foo.last == 'undefined')
foo.last = Date.now();
var now = Date.now();
if (now - 1000 > foo.time)
foo.last = now;
setTimeout(function()
{
console.log(a);
}, (foo.last += 1000) - now);
}
This will queue each console.log call with intervals of 1 second, the first call will also be delayed by 1 second.
You could do this:
function foo() {
console.log(“ran”);
}
setInterval(foo, 1000);
In the last line, writing foo() without parenthesis is intentional. The line doesn’t work if you add parentheses.

Javascript - Disable all nested functions for some time after one function function has been executed

After a function has run I want to disable a whole set of functions can be executed again. I thought the most logical way would be to put them all together inside an overarching function (in this case function run) and disable that function for some time.
So for example in the code below, when function exampleOne is executed I want to disable the whole run function for X time before it can run again.
function run(){
function exampleOne(){
// Code
sleep(1000);
}
function exampleTwo(){
// Code
sleep(1000);
}
}
run();
Take a look at underscore.js and especially the throttle or debounce functions.
You can define your functions as variables then you can disable them by assigning an empty or error functions to these variables. Two functions (e.g. enable/disable) can be responsible to disable/enable the whole set of functions. and of course you can use setTimeout to manage the delay.
for example:
var exampleOne, exampleTwo;
function enable(){
exampleOne = function(){
// do something
disable();
setTimeout(function() { enable(); }, 10000);
}
exampleTwo = function(){
// do something
disable();
setTimeout(function() { enable(); }, 10000);
}
}
function disable(){
exampleOne = function(){
Alert("i'm sleep!")
}
exampleTwo = function(){
// do nothing
}
}
enable();

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 fires Ajax call twice every time

I have the following JS code:
var delay = 5000;
function init() {
setInterval(getFileCount, delay);
}
function getFileCount() {
$.get('/notification/course-file-count', function(response) {
if (response.items.length === 0) {
return false;
}
// Do stuff with response
});
}
On page load I'm calling the init() function. The idea is to start the interval and call the getFileCount() function every 5 seconds.
So, the interval waits 5s after the page loads and runs, but it always makes the Ajax call twice.
What am I missing?
UPDATE:
I know the init() function is triggered twice on page load (thanks to the comment by Yury Tarabanko). I don't quite understand, why. The almost-full code:
$(function() {
'use strict';
function handleCourseNotification() {
var delay = 5000;
function init() {
setInterval(getFileCount, delay);
}
function getFileCount() {
$.get('/notification/course-file-count', function(response) {
if (response.items.length === 0) {
return false;
}
updateCourseList(response.items);
});
}
function updateCourseList(items) {
// update course list...
}
return {
init: init
};
}
if ($('#js-auth-course-list').length) {
var notificationHandler = handleCourseNotification();
notificationHandler.init();
}
});
It's a small module, which I initialize after page load, if a specific element is available in the DOM - $('#js-auth-course-list'). Why is init called 2 times actually? I directly call it once.
In general, it is not a good idea to call asynchronous calls inside a setInterval() because you do not know the exact response time. So, you could end up calling the second async function before the response from the first call has returned.
You can try with setTimeout() like this:
var delay = 5000;
var async = function() {
$.get('/notification/course-file-count', function(response) {
if (response.items.length === 0) {
return false;
}
// Do stuff with response
// Call the async function again
setTimeout(function() {
async();
}, delay);
});
}
async();

setTimeout() not working properly

Here is my code
(function() {
(function DeleteREG(i) {
setTimeout(function() {
if (i > 0) {
setTimeout(function stop_() {
alert(i);
}, 2000);
setTimeout(function() {
i--;
DeleteREG(i);
}, 800);
}
}, 4000);
})(5);
})();
According to the code it should alert at i=5,4,3,2,1.But it alerts at i=4,3,2,1,0.Can anyone please explain me why it is not working?what should be rectified to the code to work properly?Same thing happens for the following code also
(function() {
(function DeleteREG(i) {
setTimeout(function() {
if (i > 0) {
setTimeout(function stop_() {
alert(i);
}, 2000);
i--;
DeleteREG(i);
}
}, 4000);
})(5);
})();
And please explain me the solution in written format.How to get rid of this problem?
When you call setTimeout, your code doesn't stop.
Those two functions defined here :
setTimeout(function stop_() {
alert(i);
}, 2000);
setTimeout(function() {
i--;
DeleteREG(i);
}, 800);
They're called 2000 and 800 ms after the same moment. That's why i-- comes before the alert of the first callback.
A "solution" might be to chain the first of those callback in the second one :
(function() {
(function DeleteREG(i) {
setTimeout(function() {
if (i > 0) {
setTimeout(function stop_() {
console.log(i);
setTimeout(function() {
i--;
DeleteREG(i);
}, 80);
}, 200);
}
}, 400);
})(5);
})();
the functions that are passed to the 2 setTimeouts are created in the same execution scope ( an execution scope is created when a function is executed ) that's why they share the same i variable. The second callback will be fired before the first, therefore altering the i variable.
setTimeout pushes a message into a message queue after x milliseconds have passed, x being the time you passed as the second parameter. Anyway, the callback passed to setTimeout will always run after the current stack has been finished. This happens even if you pass 0 milliseconds ( read more details here).
UPDATE: I'm not sure what are you trying to achieve, but if you want to count from 5 to 1, this would do:
var delay = 1000;
function doStuff (i) {
if ( i > 0 ) {
alert(i);
i -= 1;
setTimeout(function () {
doStuff(i);
}, delay);
}
}
doStuff(5);
Check Out if you're not using throttling options on chrome. It can simulate a slow device, changing timing for intervals.

Categories