Javascript function call into loop each time - javascript

I have function called rotator(id): this function animate div and I can called this function with different id for animate different elements
Actually I use 5 differents id , 1,2,3,4,5
And for call I need put :
rotador(1);rotador(2);rotador(3);rotador(4);rotador(5);
The problem it´s that I want to rotate in automatic mode. For this I think to use this
for (i=0;i<=5;i++) {
setTimeout(rotador(i),2000);
}
But it doesn't work because it animates all in the same time, no let firt execute the first and continue before of first go second , etc , etc and when go the end or number 5 start other time in one
My problem it´s this if you can help me THANKS !!! :) Regards

You are actually calling the rodator(i) function, and schedule for execution after 2 seconds the result of the rodator. In other words, your code is now equalent to:
for (i=0;i<=5;i++) {
var result = rotador(i);
setTimeout(result,2000);
}
You can accomplish this either by creating a function for the callback:
for (i=0;i<=5;i++) {
setTimeout((function(i){
return function(){
rotador(i);
}
})(i),2000 * i);
}
or you can call the next rodator in the rotador function itself:
var rotador = function(i){
// your code
if (i < 5) {
setTimeout(function(){rotaror(i + 1);}, 2000);
}
}
Note: the closure in the second example is needed to call the function with the correct value of i. We are creating an anonymous function, and create i as a local scope variable, which value won't be mutated by the outerscope changes. (we can rename i to n in the local scope, if this would be more readable). Otherwise the value of i will be 5 each time rotador is called, as the value of i would be modified before the actual function call.

since setTimeout() does not wait for the function to be executed before continuing, you have to set the delay to a different value for different items, something like 2000 * (i + 1) instead of just 2000
EDIT: yes, and you need the callback as Darhazer suggests

rotationStep(1);
function rotador(id)
{
console.log(id);
}
function rotationStep( currentId )
{
rotador(currentId);
var nextId = currentId<5 ? currentId+1 : 1;
setTimeout(function(){ rotationStep(nextId) },2000); //anonymous function is a way to pass parameter in IE
}

Use a callback:
setTimeout(function() {
rotador(i)
}, 2000)

Related

setInterval call to function with other arg

I have a function called "showCustomer" that get number between 1-5 and return something.
I want to use setInterval, to run this function every 5 second but with another number.
Its not working, i don't understand why its not working to me. here is the code.
setInterval(function () {
var i = 1;
showCustomer(i);
i++;
}, 5000);
Just move the declaration of variable i before the setInterval() call:
var i = 1;
setInterval(function () {
showCustomer(i);
i++;
}, 5000);
The anonymous function you've set as a callback for setInterval gets called every 5 seconds in your code. In every call, you're setting i to 1 which resets it every time.
Moving i outside the setInterval callback makes it persist the the current value.
Every time you use var, you redeclare the value of that variable. So you only should declare the counter one time.
Every time that the browser calls the callback showCustomer the if statement evaluates if the browser should make a new call.
clearInvertal() it's the method to stop the setInterval() method.
var id = 1;
var show5times = window.setInterval(showCustomer, 5000);
function showCustomer() {
alert(id);
id++;
if(id > 5) {
window.clearInterval(show5times);
}
}

Jquery setTimeout not working if used without alert

I am implementing this code.
$('.mcqtd').click(function(){
var choice = this.id;
checkanswer(choice,questions[x].correctAnswer);
window.setTimeout(showquestion(x+1,0),3000); // 1 seconds
});
}
function checkanswer(answer,original){
if (answer=='choice'+original){
$('#choice'+original).css('backgroundColor', '#DD792E');
$('#choice'+original).append("<span class='padding10 mcqsymbol'><img src='images/right_icon.png' /></span>");
} else {
$('#'+answer).css('backgroundColor', '#AFA689');
$('#'+answer).append("<span class='padding10 mcqsymbol'><img src='images/wrong_icon.png' /></span>");
$('#choice'+original).css('backgroundColor', '#DD792E');
$('#choice'+original).append("<span class='padding10 mcqsymbol'><img src='images/right_icon.png' /></span>");
}
}
Onclick, the tds should be highlighted, and after 3 seconds, the next question should be loaded but this is not happening, after 3 seconds the next question is being loaded, but backgrounds are not changing. If I alert something inside checkanswer(), the code works. Any ideas what should I do?
The to executing part must be wrapped in a anonymous function if you want to use parametes. Otherwise it is not working in setTimeout.
setTimeout(function() {
showquestion(x + 1, 0);
}, 3000);
As A.Wolff noted in the comments below, you can even pass parameters to a called function in setTimeout by extening the parameters behind the time.
// note there are no '()' behind the function name
setTimeout(showquestion, 3000, x + 1, 0);
If you would call a function without parameters you can left out the wrapper function and the additional parameters too.
// note there are no '()' behind the function name
setTimeout(functionWithoutParameter, 3000);
What you do is calling the function directly and passing it's return value over to setTimeout. As you intend to use arguments with this, you will have to make use of an anonymous function, eg:
setTimeout(function(){ showquestion(x+1, 0);}, 3000);
Edit:
If you only have a functioncall without arguments it woulf look like:
setTimeout("foo()", 3000);
or
setTimeout(foo, 3000);
Dirtly call this in setTimeout method its not working.
setTimeout(question, 3000);
function question() {
showquestion(x + 1, 0)
}

variables scope in nested javascript function calls

In the below code, I want to know what would be the value of tabId inside doStuffWithReport function. Would it be the same value of tabId that was sent while calling sendMessage or it might change during the course of period?
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
// we suppose that tabId is 5.
function doStuffWithReport(report) {
// what would be the value of tabId? still 5? or it might change to
// something else if, in the meantime, we received another
// call for chrome.tabs.onUpdated?
}
// we are sending a message to tabId 5.
chrome.tabs.sendMessage(tabId, {
text: 'report_me'
}, doStuffWithReport);
});
Edit: I tested it myself. It remains the same, i.e., tabId would remain 5 even if there is another call on chrome.tab.onUpdated.
Well, first let's simplify the code to look at the underlying behavior:
function outside(){
var out = 5;
function inside(){
console.log(out);
}
inside();
}
In this example it will obviously print out 5 when outside is called, but since inside is only defined locally, it will be undefined unless called from within outside.
To make it a bit more complex, let's not make out static and have it based on a parameter:
function outside(out){
function inside(){
console.log(out);
}
inside();
}
Now it is pretty much the same as before and will print out whatever we use as a parameter right away. Let's make it a bit more async by having inside be called after a random amount of time of up to a second and compare the then current value of out with the value of out that is printed at the time inside is called while calling it several times consecutively.
function outside(out){
function inside(){
var dt = Date.now();
console.log(dt + ' : ' +out);
}
var n = Math.floor(Math.random() * 1000);
var d = Date.now()+n;
console.log(d + ' : ' + out);
setTimeout(inside,n);
}
for(var x=0;x<25;x++){outside(x);}
From the output of this, we can see that the value of out that inside has at the time of being called is the same value as when we set the timeout for inside to be called.
From this we can say that tabId would indeed still be 5 when doStuffWithReport is called.

JavaScript: window.setTimeout(), force early expire

I have a <div> on my page that refreshes automatically every two minutes with updated log entries. When I first load my webpage, I call the following function.
function getLogs() {
var filter = $('#filter').val();
$.get("index-ajax.asp", { queryType: "getLogs", filter: filter,
uTime: new Date().getTime() },
function(data){
$("#logEntries").html(data);
window.setTimeout("getLogs()",120000);
});
}
I know the above code could be cleaner with window.setInterval(...); but I just like the control of window.setTimeout(...);.
My question, is it possible to cancel the next timeout execution? In the event that I change the filter, I'd like to cancel the next timeout, and call the function right away, which would reschedule the timeout function. Is there a better way to achieve that result?
Note that the above code is in jQuery.
Yes, use clearTimeout.
Ex:
var clr = window.setTimeout(getLogs,120000);
The when you wan to clear it:
clearTimeout(clr);
setTimeout returns a timerID that you can pass to clearTimeout:
// Note we are passing the *function* rather than a string
// Also note the lack of () - we are *not* calling the function
// setTimeout will do that for us
var timerID = setTimeout(getLogs, 120000);
// Fake condition - we cancel the timer if the timerID is even
if (timerID % 2 === 0) {
clearTimeout(timerID);
}
You could always define a new variable based on a filter value and if that filter value is set, use a while statement to omit the timeout:
if(filter == "whatevs"){
var i=true;
}
function(data){
$("#logEntries").html(data);
while(i!=true){
window.setTimeout("getLogs()",120000);
}
}

I want to draw on a canvas with a certain interval and setTimeout isn't working

Here is the part of the code that matters:
function drawCircle(i, color1, color2) {
var ctx = canvas.getContext("2d");
if (i % 2 == 1) {
ctx.fillStyle = color1;
}
else {
ctx.fillStyle = color2;
}
ctx.beginPath();
ctx.arc(110, 270, 10, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
for (var i = 0; i < 10; i++) {
setTimeout(drawCircle(i, color2, color5), 4000);
}
Note that this is just a snippet I wanted to try out before I use code similar to this on a larger project. This isn't working properly, the image is only drawn once, that is, I only see the last circle that is drawn. I have googled this to death but nothing has helped me so far.
What you want to use is setInterval. setTimeout just fires the event once. They have the same argument list.
Also I don't think the way you use setTimeout is correct. The way you've written it now, the function is fired before actually passing anything to setTimeout/setInterval. So you should write:
setInterval(function() { // GOOD. An actual function is passed
drawCircle(...); // as the first argument.
}, 4000);
or:
setInterval('drawCircle(...)', 4000); // GOOD. the JS statement is supplied as
// a string and later on will be evaluated
// and executed with eval().
and NOT:
setInterval(drawCircle(...), 4000); // BAD! drawCircle() is fired, its result
// evaluated and passed on to setInterval
// that doesn't know what to do with it.
EDIT
You don't have any blocking routines in JavaScript. It's a single threaded, event driven language. If you call something like setInterval it succeeds immediately. Only after 4 seconds or so your callback function will be invoked. However in the meantime JS will be busy doing all sort of different stuff - like for example reacting to other events generated by the user. What you want to do is to call setTimeout once and then inside the callback function, just before returning invoke it again with the same function and a different set of arguments of i. Something along these lines:
function drawCircle(i, ...) {
// ... do stuff ...
if (i < 10) { // Check if the callback has been invoked 10
// times already.
setTimeout(function() { // Schedule the callback for execution
drawCircle(i + 1, ...); // again after anoter 4 seconds.
}, 4000);
}
}
setTimeout(function() { // Invoke the callback the first time
drawCircle(1, ...); // after first 4 seconds.
}, 4000);
There are actually a couple of things that are causing your code to misbehave, and they're all in how your loop is written. The first problem is the call to setTimeout, mainly that you're not passing a function object to it as the first argument, and most people would fix that by doing something like this:
for (var i = 0; i < 10; i++) {
setTimeout(function() {
drawCircle(i, color2, color5);
}, 4000);
}
That will cause the setTimeout to delay as you expected, but it will end up calling drawCircle with 10 as the first argument 10 times, and that is because of every call is using the same reference to the "i" variable. The value for i isn't retrieved until the call is made...4 seconds or so after the loop completed when i is already 10.
To get around that, you need one more function:
function getDrawer(i, color2, color5) {
return function() {
drawCircle(i, color2, color5);
}
}
for (var i = 0; i < 10; i++) {
setTimeout(getDrawer(i, color2, color5), 4000);
}
The getDrawer (a horrible name, please don't use it) function is called immediately, so the value of i is accessed immediately and remembered by the anonymous function that getDrawer returns. That anonymous function is what will be called by setTimeout.
The issue here is that you're calling setTimeout several times in a row, rather than calling it again from the callback. Try moving the call to setTimeout to the end of the drawCircle function to see the animation.

Categories

Resources