Incorrect usage of setTimeout? - javascript

I've written a script that fires off 2 URLs based on some random number logic and I'm trying to set a delay before either one is fired (of half a second) but I don't think it's working properly. Am I doing this correctly? Code is below:
var clicks = "http://www.urlone.com";
var impressions = "http://www.urltwo.com";
var randomNumber = (Math.random()*100);
function callOut() {
for (var i = 0; i < lengthVal; i++){
if (randomNumber < 75) {
var randomCounter = (Math.random()*100);
if (randomCounter < 50) {
setTimeout("image1.src = clicks;",500);
}
else if (randomCounter > 50) {
setTimeout("image1.src = impressions;",500);
}
}
}
}

setTimeout first parameter should be a function. Not string of code.
code in the alternate syntax, is a string of code you want to execute after delay milliseconds. (Using this syntax is not recommended for the same reasons as using eval())
MDN
setTimeout(function(){...}, 500);

Taken from here: http://www.codescream.com/?p=18 read it it should help :)
If you want to make a delay with setTimeout you should do exactly this:
setTimeout( function () {
doThings()
}, 1000);
and never this:
setTimeout( "doThings()", 1000);

setTimeout("image1.src = clicks;",500);
For this image1 must be declared in a global context, like this:
var image1 = document.getElementById('image1');
But you better use a function here.
function setImageSrcClicks(){
document.getElementById('image1').src = 'http://clicks_url';
}
setTimeout(setImageSrcClicks,500);

Duly noted about using setTimeout with a string. Here is how I ended up doing it. Is this the 'best' way to do this?
var clicks = "http://www.urlone.com";
var impressions = "http://www.urltwo.com";
var conversions = "http://www.urlthree";
var lengthVal = (Math.random() * 20 + 20);
var image1 = new Image();
var image2 = new Image();
var globalCounter = -1;
function callOut() {
var ord = (Math.random() * 9999999999999) + "";
var randomNumber = (Math.random() * 100); // Random value for each call
if (randomNumber < 75) {
var randomCounter = Math.random() * 100;
alert(randomCounter);
if (randomCounter < 50) {
image1.src = clicks + ord + "?";
}
if (randomCounter > 50) {
image2.src = impressions + ord + "?";
}
}
if (globalCounter++ < lengthVal) {
setTimeout(callOut, 1000); // Call itself after another second
}
}

Related

setInterval won't call function

I'm trying to create a sort of ecosystem where objects spawn over time. However, when I try using setInterval to increase the amount it doesn't work. It works when I call the function on its own, but not when I use setInterval.
var plantSpawn = 5;
function createPlants() {
setInterval(reproducePlants, 5000);
for(var i=0; i<plantSpawn; i++){
var plant = new Object();
plant.x = Math.random() * canvas.width;
plant.y = Math.random() * canvas.height;
plant.rad = 2;
plant.skin = 'green';
myPlants[i] = plant;
}
}
function reproducePlants() {
plantSpawn += 5;
}
My goal for this is for every 5 seconds, 5 new plants appear. However, when I use the reproducePlants function with setInterval it does not work.
Note: I am calling createPlants() later in my code which makes the first 5 plants show up, but the next 5 won't show up. I am just showing the code that I'm trying to fix
The creation code must be moved inside the function that is repeatedly called.
NOTE: This is not an efficient way if you are going to call reproducePlants infinitely many times, since the myPlants array is reconstructed every time.
// Init with 0, because we increment it inside reproduce Plants
var plantSpawn = 0;
var myPlants = [];
function createPlants() {
reproducePlants();
setInterval(reproducePlants, 5000);
}
function reproducePlants() {
const canvas = document.getElementsByTagName('canvas')[0];
plantSpawn += 5;
for(var i = 0; i < plantSpawn; i++) {
var plant = new Object();
plant.x = Math.random() * canvas.width;
plant.y = Math.random() * canvas.height;
plant.rad = 2;
plant.skin = 'green';
myPlants[i] = plant;
}
}
You don't necessarily need to call the createPlants function from the reproducePlants function. You could add a call after both the functions. If I understand what you are trying to achieve that should do it.
You need to move the code that creates the plants (the for() chunck) inside the function that is called every 5 seconds (reproduce plants). So each time the function is called it will create the plants.
If you are trying to add only the 5 new plants every 5 seconds to your plants array you shouldn't recreate the array each time. It's better to keep track of the last index you have added and then continue right after that.
I created a variable called lastCreatedIndex so you can understand better what is going on. So the first time the code will run plants[i] from 0 to 4, the second 5 to 9...
var myPlants = [];
var lastCreatedIndex;
var plantSpawn;
function createPlants() {
plantSpawn = 5; //Initialize with 5 plants
lastCreatedIndex = 0; // Starts from index 0
reproducePlants();
setInterval(reproducePlants, 5000);
}
function reproducePlants() {
for(var i = 0 + lastCreatedIndex; i < plantSpawn; i++) {
var plant = new Object();
plant.x = Math.random() * canvas.width;
plant.y = Math.random() * canvas.height;
plant.rad = 2;
plant.skin = 'green';
myPlants[i] = plant;
console.log(i); // Output the number of the plant that has been added
}
lastCreatedIndex = i; //Update the last index value
plantSpawn += 5;
}

Calling a function if an operation is not true

I have not seen anything that specifically answers this question.
I intend to develop a text-based game that involves an action occurring every time an idle bar fills up(every x seconds passes)
I'm just trying to figure out the very basic layout of my javascript that will make the battling system in this game.
I'm trying to make the computer re-calculate pDamThisRound if pDamThisRound is not > baseD which is this case is 10.
If it is greater than baseD my code works and prints pDamThisRound. But if it isn't the code just prints nothing.
var baseD = 10;
var pStr = 25;
var pDam = Math.floor((baseD + pStr) / 2);
var pDamThisRound;
var pDamTR = function() {
pDamThisRound = (Math.floor(Math.random() * 2 * pDam));
};
pDamTR();
if(pDamThisRound > baseD) {
document.getElementById("h").innerHTML = pDamThisRound;
}
else {
pDamTR();
}
https://jsfiddle.net/qfnvf1y8/4/
the code just prints nothing
That's because there isn't any code which prints anything. Look at your else block:
else {
pDamTR();
}
What does that function do?:
var pDamTR = function() {
pDamThisRound = (Math.floor(Math.random() * 2 * pDam));
};
Nowhere do you produce any output.
Basically, if you want to print something then, well, print something. Just like you already do in your if block. For example:
document.getElementById("h").innerHTML = "something";
The function pDamTR is probably executing, the problem is that its assigning something to a variable, but doing nothing with it.
Here you go, a corrected version with a while operator:
https://jsfiddle.net/qfnvf1y8/6/
var baseD = 10;
var pStr = 25;
var pDam = Math.floor((baseD + pStr) / 2);
var pDamThisRound;
var pDamTR = function() {
pDamThisRound = (Math.floor(Math.random() * 2 * pDam));
};
pDamTR();
while(pDamThisRound <= baseD) {
pDamTR();
}
if(pDamThisRound > baseD) {
document.getElementById("h").innerHTML = pDamThisRound;
}
else {
pDamTR();
}
Regards,
Eugene
Several mistakes:
1) your else branch does not print anything
2) if you want pDamThisRound > baseD you need a while loop
while(pDamThisRound <= baseD) {
pDamTR();
}
printpDamTR();
function printpDamTR(){
document.getElementById("h").innerHTML = pDamThisRound;
}
The function printpDamTR would not be necessary, but it generally is a good idea to encapsulate such things, as you are probably going to use it more often. Also it increases the maintainability of your code since you loosen the dependencies between your JS and your HTML.
You can use setTimeout to help you, with something like this:
var baseD = 10;
var pStr = 25;
var pDam = Math.floor((baseD + pStr) / 2);
var timeoutDuration = 3000; // 3 seconds
window.setTimeout(function () {
// execute the check and the update logic here
var pDamThisRound = (Math.floor(Math.random() * 2 * pDam));
if(pDamThisRound > baseD) {
document.getElementById("h").innerHTML = pDamThisRound;
}
}, timeoutDuration);
This will execute the check every 3 seconds

Javascript SetTimeout and Loops [duplicate]

This question already has answers here:
How do I add a delay in a JavaScript loop?
(32 answers)
Closed 9 years ago.
Experts.
Javascript not producing desired delay effect.
From other questions, on SO I got to know that, problem is with settimeout and the way I am using it.
But still I am not able to comprehend, how Settimeout works.
So I am putting code here.
Need to use Javascript only, because of knowledge purpose.
Actually I am trying to clear my concepts about this, closure in javascript.
Are they kind of twisted things of Javascript?
var objImg = new Object();
var h;
var w;
var no = 100;
while (no != 500) {
setTimeout(function () {
size(no, no);
}, 2000);
/* it's get executed once, instead of repeating with while loop
Does it leave loop in mid? I get image with 500px height and
width, but effect is not acheived.
*/
no = no + 50;
}
function size(h, w) {
var objImg = document.getElementsByName('ford').item(0);
objImg.style.height = h + 'px';
objImg.style.width = w + 'px';
}
You have two problems :
no will have the value of end of loop when the callback is called
you're programming all your timeouts 2000 ms from the same time, the time the loop run.
Here's how you could fix that :
var t = 0
while (no != 500) {
(function(no) {
t += 2000;
setTimeout(function() { size(no,no);} ,t);
})(no);
no = no+50; // could be written no += 50
}
The immediately executed function creates a scope which protects the value of no.
A little explanation about (function(no) { :
The scope of a variable is either
the global scope
a function
The code above could have been written as
var t = 0
while (no != 500) {
(function(no2) {
t += 2000;
setTimeout(function() { size(no2,no2);} ,t);
})(no);
no += 50;
}
Here it's probably more clear that we have two variables :
no, whose value changes with each iteration and is 500 when the timeouts are called
no2, in fact one variable no2 per call of the inner anonymous function
Each time the inner anonymous function is called, it declares a new no2 variable, whose value is no at the time of call (during iteration). This variable no2 is thus protected and is used by the callback given to setTimeout.
Why not just use setInterval() instead?
var objImg = new Object();
var h;
var w;
var no = 100;
var myInterval = window.setInterval(function() {
size(no, no);
no = no + 50;
if (no >= 500) clearInterval(myInterval);
}, 2000);
function size(h, w) {
var objImg = document.getElementsByName('ford').item(0);
objImg.style.height = h + 'px';
objImg.style.width = w + 'px';
}
Your problem is with your size() function syntax & algorithm:
var objImg = new Object();
var h;
var w;
var no = 100;
var int = window.setInterval(function () {
size(no,no);
no += 50;
},2000)
function size(h, w) {
if (h == 500){
window.clearInterval(int);
return;
}
var height = h + 'px';
var width = w + 'px';
document.getElementsByName('ford').item(0).style.height = height;
document.getElementsByName('ford').item(0).style.width = width;
}
http://jsfiddle.net/AQtNY/2/

Timed loop, 10 second between

I currently got this:
var xnumLow = 3000;
var xnumHigh = 4900;
var ynumLow = 9969;
var ynumHigh = 13900;
var ts = Math.round((new Date()).getTime() / 1000);
for (y=ynumLow; y<ynumLow; y++)
{
for(x=xnumLow; x<xnumHigh; x++)
{
$('#box').append(y + " - " + x);
}
}
Now I would like it to append new whole y "row" every 10 seconds, so they all dont append all in once.
The y "row" is the outer for() loop
How can I do this?
I got:
var refreshId = setInterval(function(){ (...) }, 10000);
But I don't know where to merge this with the above code, in order to work correct.
(function () {
var xnumLow = 3000,
xnumHigh = 4900,
ynumLow = 9969,
ynumHigh = 13900,
currentY = ynumLow,
delay = 500,
displayData = function () {
var out = [],
x;
for (x=xnumLow; x<xnumHigh; x++) {
out.push( currentY + "-" + x );
}
console.log(out.join(",")); //do the append here
currentY++;
if (currentY<ynumHigh) {
window.setTimeout(displayData,delay);
}
};
displayData()
})();
setInterval(function () {
// code that appends a box
}, 10000);
https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
var y = ynumLow;
function addRow()
{
for (x = xnumLow; x < xnumHigh; x++) {
$('#box').append(y + " - " + x);
}
if (y++ < ynumHigh)
refreshId = setTimeout(addRow, 10000);
}
addRow();
edited as Pete suggested for clarity
I would do it something like this:
var xnumLow = 3000;
var xnumHigh = 4900;
var ynumLow = 9969;
var ynumHigh = 13900;
var x, y = ynumLow; //don't forget to declare your variables!
var ts = Math.round((new Date()).getTime() / 1000);
(function addYRow() { //Create a function that adds the X elements
for(x=xnumLow; x<xnumHigh; x++)
{
$('#box').append(y + " - " + x);
}
y++; //don't forget to increment y
if(y < ynumHigh) { //only re-call if we aren't done yet
setTimeout(addYRow, 10000); //Recall the function every 10 seconds.
}
}());
Looking at some of the other answers, it's important to realize that you don't want to set up a bunch of things to happen 10 seconds from a given point (which is what happens if you do a loop calling setTimeout(). Instead, I assume you want to add a row, then wait 10 seconds, then add another row. This can only be achieved by adding a row (usiny, in my case, the addYRow() function), then delaying 10 seconds before re-calling the add-a-row function.
Column Delay:
In response to the question about how to do a 500ms delay in the x row, that's a little tricky, but not too bad. You just have to nest things one more time:
var y = ynumLow; //don't forget to declare your variables!
var ts = Math.round((new Date()).getTime() / 1000);
(function addYRow() { //Create a function that adds the X elements
var x = xnumLow;
(function addXCol() { //Create a function that adds each X element
$('#box').append(y + " - " + x);
x++;
if(x < xnumHigh) { //if x is not done, call addXCol 500ms later
setTimeout(addXCol, 500);
} else {
y++;
if(y < ynumHigh) { //If x is done but y isn't, call addYRow 10 seconds later
setTimeout(addYRow, 10000); //Recall the function every 10 seconds.
}
}
}());
}());
Note that if you want to delay the start of the column/row addition (e.g., if you want to put a 500ms delay between when a row is added and when the first column is added, you'll need to adjust the addXCol() expression creation to look like this:
setTimeout(function addXCol() { //Create a function that adds each X element
//...
}, 500);
This will put that initial delay in. Hope that helps.
Something like this?
var refreshId = setInterval(function(){
$('#box').append(++y + " - " + x);
}, 10000);

setInterval delays

I'm trying to execute a rotating banner (Calling it through an array). I set an interval but the image only shows after 10 seconds (10000) and only then begins the rotation. I removed the cluttered HTML of the array, but here's the rest of it:
var current = 0;
var banners = new Array();
banners[0]=;
banners[1]=;
banners[2]=;
banners[3]=;
var myTimeout = setInterval("rotater()",10000);
function rotater() {
document.getElementById("placeholderlayer").innerHTML=banners[current];
if(current==banners.length-1){
current = 1;
}else{
current += 1;
}
}
window.onload = rotater();
window.onload = rotater;
is the correct syntax. You don't want to call the function. However, the bulletproof solution is rather this:
onload = function() {
rotater();
window.myTimeout = setInterval(rotater, 10000); // Never pass a string to `setInterval`.
};
ProTip™: Don't use new Array(), use an array literal. For example, this:
var arr = new Array();
arr[0] = 'Hello';
arr[1] = 'world!';
Should be written as:
var arr = ['Hello', 'world!'];
Just a comment:
Instead of:
if(current==banners.length-1) {
current = 1;
} else {
current += 1;
}
you can do:
current = ++current % banners.length;

Categories