I have an array of URL's and I want to go to every page to parse some information. I do:
var numbers = ["1111", "2222", "3333"];
function parse(page){...
}
function set(page){
console.log(page);
window.location = page;
parse (page);
}
for (j=0,m = numbers.length; j<m; j++){
page="http://www.*****/*****/"+numbers[j]+"/*****/";
setInterval(set(page), 10000);
}
But it's not working because browser tries to download pages and at the end, only the last one will be displayed. Function "parse" does not parse pages. How to fix my code?
setInterval will call your set function once every 10 seconds the way you have invoked it. The for loop will have ended before that time, and the page's value at that time will be:
"http://www.*****/*****/3333/*****/";
So after 10 seconds you will only see that page displayed.
Try use setTimeout combine with recursive call.
const MAX=100;
setPage(num){
parse()
if(num<MAX)
setTimeout(setPage(num+1), 10000);
}
When you use setInterval(), you just tells the browser to carry out set() function after 10 seconds, and because all the setInterval() are been called in a very short period of time in that for loop, they will carry out the task together as well, then set will be carried out thrice, first with "1111" then "2222" and "3333".
It would seems like it only run the last one with "3333".
I suggest you use setInterval() only once, while the page variable will be created with a counter.
var counter=0
function count(){
page="http://www.*****/*****/"+numbers[counter]+"/*****/";
set(page);
counter+=1;
if(counter>=numbers.length){
counter=0;
}
}
setInterval(count(), 10000);
It is due to Scopes and Closures in JS. The solution for the problem is to create IIFE(Immediately Invoked Function Expression) inside loop!
for (var i=1; i<=5; i++) {
page="http://www.*****/*****/"+numbers[j]+"/*****/";
(function(j){
setTimeout( set(page), 10000 );
})( i );
}
If you have time, refer about Closures in JS!
Related
I've encountered a very badly designed website, and most of the "dynamic" content on the site is changed within setTimeout/setInterval functions.
There is one very annoying setInterval function which checks page activity very quickly, and I would like to override this function.
What I tried is clearing all the setInterval values, one by one to check if the function stopped. Also, clearing all the possible setInterval values like this: for(let i = 0; i < 1000; i++) clearInterval(i);, stops the "dynamic" page rendering, WHICH I DONT WANT TO
Question: 1. is there any way to look into the interval or timeout function and clear them?
2. is there a better way?
My current solution: I'm overriding the setInterval and setTimeout before page loaded, and log the function .toString() within.
The short answer is no, you cannot determine anything about the setTimeout/setInterval callback given a timerId. It sounds as if you don't have access to edit the underlying Javascript to prevent this action. If you can get your JS to load before the code in the page, then what you can do is replace setInterval or setTimeout with your own code, where you can increase the interval to whatever you want. For example:
let setTimeoutOld = setTimeout;
setTimeout = (cb, interval) => {
if (interval < 1000) {
interval = 1000;
}
setTimeoutOld(cb, interval);
}
Now if the page does something like:
setTimeout(() => { console.log('fired') }, 1);
The timeout won't fire until at least 1000ms have passed. If you only wanted to modify a specific setTimeout based on the contents of the cb, you could do what you mentioned in your work-around: calling .toString() on the function and comparing it to some previously generated .toString() (partial or complete) and then doing whatever you wanted.
I assume you have access to code wherever it's setting timeout or interval.
So just take a global array and push it's output to it. Then iterate that array to clear everything.
For ex.
timeouts = [];
now, in code where there's timeout like
var timeout = setTimeout(<callback> , <interval> ); // push it's output to that global.
timeouts.push(timeout);
Then at the very end clear that.
for(time of timeouts) {
clearTimeout(time);
}
Similarly, for Interval.
Hope this is what you are looking for.
I im programming tv remote control using javascript and need when user press number 1 function waits 2 seconds if user press one more time 1 (1 channel or 11 channel or 111channel).
i write this function but it gets on display only 11111111 in loop here is my code:
function chChannel(pressed) {
setInterval(function () {
if (lengthCS < 3) {
inputChannel += pressed;
lengthCS = inputChannel.length;
}
}, 2000);
// call function to change channel using variable value inputChannel for ex. 011
};
Any solution please?
So function need to wait 2seconds and then after 2seconds it gets value of pressed numbers in variable InputChannel so that i can then call function to change channel to number from Value InputChannel.
Listening to keypresses and counting them is one well documented thing, but, in context with the actual topic, I would say, there is no correct Waiting method, other than to end the script with a timeout call being set to a function that repeatedly checks, whether the Time to wait has passed by, if not then selftrigger with setTimeout in eg. 100ms, if yes then call a function that continues the main program.
The Waiting thread may then also check and count keypresses, eg. in global variables as a basic solution.
use "setTimeout".
var Timer;
function chChannel(pressed) {
clearTimeout(Timer);
Timer = setTimeout(function () {
if (lengthCS < 3) {
inputChannel += pressed;
lengthCS = inputChannel.length;
}
}, 2000);
// call function to change channel using variable value inputChannel for ex. 011
};
Have you considered using something like underscore's debounce function, would make things a lot simpler all round.
http://underscorejs.org/#debounce
May be something like this might work, on phone can't test it myself...
var inputChannel;
function chChannel(pressed) {
if (inputChannel <= 3) {
inputChannel += pressed;
}
else {
inputChannel = pressed;
}
_.debounce(someFunction, 2000);
};
As long as debounce keeps getting called within the delay it will not execute, and only execute once after the delay.
I am trying to load a random image at a random time. For some reason this is not randomizing the time, though it does randomize the image. Any ideas what's wrong?
var randomTime2 = 3000; //initialize the random time with this value to start
setInterval(function(){
var randomNum = Math.floor((Math.random()*3)+1);//random num for image
$('.recent-project2 img').fadeTo('slow',0,function(){
var randomImg = "img/recent-projects-"+randomNum+".jpg";
$('.recent-project2 img').attr('src',randomImg);
$('.recent-project2 img').fadeTo('slow',1);
});
randomTime2 = Math.floor(Math.random()*10000);//reset random time
return randomTime2; //return random time
},randomTime2);
Use setTimeout and re-trigger at the end of the function with a random time.
The setInterval call will just add your function and the required interval to an internal table to remember to call your code when the expected delay period passed. Note however that even if you change the variable used to specify the interval this will have no effect on the internal table: that value has been read when you called setInterval and it's now stored.
To randomize the callback time give your function a name and just use setTimeout instead of setInterval:
function MyCallback() {
...
setTimeout(myCallback, new_delay);
}
setTimeout(myCallback, first_delay);
with this approach at each call you can decide a different delay before next call.
You can't change the value of randomTime2 inside the function as it's pass by value, not reference.
setInterval(someFunction, someNumberValue)
This line of code will call someFunction every someNumberValue-miliseconds. The value is not updated dynamically.
There's lots of ways you could make this work, but I suggest simply using setTimeout and making the end of someFunction call it again. For instance:
//psudo-code, might not actually run, just showing you the general idea.
var someFunction = function(){
console.log("Whatever.");
}
var repeatFunction = function(){
someFunction()
var timeoutID = window.setTimeout(repeatFunction, Math.random()*10000);
}
repeatFunction(); //Starts the loop.
Someone know if after I displays an HTML page I can access a specific ID (getElementById), and change it a value several times?
I want to present a client-side some string and change it several times according the progress of the program, but I can not, it writes to me only recently.
For example:
<script type="text/javascript">
function foo(){
for(var i = 0; i<10000; i++){
document.getElementById('myTag').innerHTML = i;
}
}
</script>
In this case, I do not see the numbers run. I see only the last one.
If I put alert inside the loop - the value is changed.
As i understand your question you want a countup from 0 to 10000 ?
and you want to see the progression on screen ? you could do something like that :
http://jsfiddle.net/camus/ayJFM/
var interval = 500;//milliseconds
var foo = (function () {
var i = 0;
var func = function () {
if (i < 10000) {
document.getElementById("myTag").innerHTML = i;
i += 1;
setTimeout(func, interval);
}
};
return func;
})();
setTimeout(foo, interval);
You're almost there. The only thing you're doing wrong is replacing the innerHTML content instead of adding to it. Change this:
document.getElementById('myTag').innerHTML = i;
to this:
document.getElementById('myTag').innerHTML += i;
Additional/alternative answer:
Wait. I've just reread your question and realized that there is another way of interpreting it. The way you ask it is quite vague so I'm leaving the above answer as is.
The reason you don't see "running numbers" as you process the for loop is because you misunderstand how javascript works in the browser.
The browser's event loop runs something like this:
1. Fetch content
2. Run javscript
3. Render content
then repeat forever
This is how javascript works. So running a simple for loop like you're doing. The browser executes the script until there is nothing else to execute (step 2). Once javascript have finished executing then it will start the render process (step 3). Obviously, by this time the value of i is the final value and therefore you only see the final value.
The browser never interrupts running javascript to render/update the page. So, how do people implement countdown timers etc? They do it by scheduling a piece of javascript to execute in the next iteration of the event loop. That is to say, the let the browser enter step 3 and at the appropriate moment as the browser enters step 2 again they run the script they want.
Javascript basically provides two ways to do this: setTimeout and setInterval.
How setTimeout works is this:
step 1. nothing to do
step 2. setTimeout schedules a piece of javascript to run at a later time
Note that the javascript does not execute yet until setTimeout
expires.
step 3. let the browser update the page
many, many loops of steps 1-3
step 2 (some time later).
setTimeout expires and the piece of javascript executes
step 3. let the browser update the page
So, the get the effect you want, you need to do it like this:
function foo(){
var i = 0;
var update = function(){
document.getElementById('myTag').innerHTML = i;
i++;
if (i<10000) {
setTimeout(update,100);
}
};
update();
}
I am trying to display a set of images at certain time intervals in my rails application. Now i am using javascript for this and taking the timings from the user for the time between each slide to be displayed. Now for that i am using the setTimeout function of javascript in which i am trying to fetch the time from the database,ie, my table named slides.
This is my code snippet for preloading images
var preloaded = new Array();
for (var x = 0; x < 10; x++)
{
preloaded[x] = new Image();
preloaded[x].src = "/images/pausch/img"+x+".gif";
}
This is my snippet of the image changing function
function slideit(){
//if browser does not support the image object, exit.
if (!document.images)
return;
document.images.slide.src=eval("preloaded["+step+"].src");
if (step<10)
step++;
else
step=0 ;
<% #slides.each do |slide| %>
setTimeout("slideit()",'<%= slide.time.to_i %>')
<% end %>
}
However the images are changing are some random times and not according to the time stored. Can anyone suggest whats wrong?
Try removing the setTimeout() call from inside the function, and put a call to (say) setInterval(slideit,1000) somewhere outside the function:
....
document.images.slide.src = preloaded[step].src;
if (step<10) step++;
else step=0;
}
setInterval(slideit,1000);
This will cause slideit() to be called every 1000 miliseconds, rather than assigning multiple timeouts each time the function is called.
Note I also removed the eval() call and some extra quotes from your preloaded[step].src line - It won't affect the timeout stuff, but you shouldn't need eval here because the contents of the array is just a string (and for security reasons it's generally good to avoid using eval() if you can).
Edit: Just saw that you want different timeouts for each image. I would do this with a single call to setTimeout():
....
document.images.slide.src = preloaded[step].src;
setTimeout(slideit,timeouts[step]);
if (step<10) step++;
else step=0;
}
For this solution, you'll want to initialise an array called timeouts where each entry timeouts[x] contains the number of miliseconds to display image x.