Slowing Down JavaScript Loop - javascript

I have a piece of JavaScript that generates every possible combination of a charset for the length provided. Since I'm using it for a length of 12, it's a very long loop that freezes and crashes the browser.
I've tried replacing the for loop with a setInterval() but it only seemed to break it.
How can I slow down my loop?
Here's the script:
var charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
charset_length = charset.length;
function recurse(width, pos, base) {
for (var i = 0; i < charset_length; i++) {
if (pos < width - 1) {
recurse(width, pos+1, base + charset[i]);
}
console.log(base + charset[i]); // replaced later
}
}
recurse(12, 0, '');
EDIT: Because each output will open a new tab (that will close itself once done), I want to slow it down so a maximum of 5 tabs approx. are open at the same time.

Related

Why does console.time show much lower time than the actual time?

I am testing a snippet of JavaScript's speed using the console.time(); method in Chrome and Chromium-based Edge. When I'm running the snippet in the browser, it takes at least 2 seconds, but the displayed result of time is around milliseconds, What is happening here?
var list = [...Array(50000000).keys()];
console.time("time");
var x = 0;
for (let i = 0, n= list.length; i<n ;i++) {
x++;
}
console.timeEnd("time");
I've tested this with performance.now() and I get the same result as time, which is really confusing however it works perfectly fine in Firefox.
Is this a Chrome/Edge bug? if it is, How can one submit an issue for chrome?
Update
Thanks to #vlaz and #Jax-p I found out that I've missed the array generation time:
console.time("time");
var list = [...Array(50000000).keys()];
var x = 0;
for (let i = 0, n= list.length; i<n ;i++) {
x++;
}
console.timeEnd("time");
Creating and spearding array with [...Array(50000000).keys()]; takes over 1.5s in my Chrome but you have timer start after that (You had. Before you change the question.). I am getting same (a little bit higher) results in Firefox. Can it be it?
Suppose there is also a delay before the browser even gets to execute JavaScript.
console.time("time");
var list = [...Array(50000000).keys()];
console.timeEnd("time");
console.time("time2");
var x = 0;
for (let i = 0, n= list.length; i<n ;i++) {
x++;
}
console.timeEnd("time2");

Javascript: Page keeps crashing when attempting to load the file?

EDIT: CSS
Javascript
My code is by no means demanding so I'm not sure why this is happening.
It doesn't seem to work on JSFiddle either. Every time I try to load it on the website I get a 404 error.
This only happened after I made a small change in my code:
function runDisplay(data, id) {
var reader = document.getElementById(id);
var index = 0;
if (timer) {
clearInterval(timer);
}
if (data.length) {
timer = setInterval(function() {
reader.innerHTML = data[index++];
var punctuation = [".", ",", ":", ";", "!", "?"];
var word = data[index++];
for (var j = 0; j < punctuation.length; j++) {
if (!(word.indexOf(punctuation[j]) === -1)) {
word = string.replace(punctuation[j], '');
}
index = index % data.length;
}, getTextSpeed()); // change speed dynamically in real time
}
}
function getTextSpeed() {
var speeds = document.getElementById("speed");
return speeds.options[speed.selectedIndex].value;
}
I changed a textSpeed variable to a direct call to the method getTextSpeed in an attempt to get the speed of the text to change dynamically.
Essentially what this class is supposed to display text word-by-word, with font-size and the speed (which must be implemented with setInterval() and clearInterval()) by which the words are displayed being changeable by the user of the webpage.
If a word contains punctuation, then it is removed and the delay between that word and the next is doubled (234 ms instead of 117 ms). If there is more than one character of punctuation (ex: ...) then only one character of punctuation is removed.
Can you help me figure out what's causing this? Is it an error in my implementation? Did I accidentally create an infinite loop somewhere?

Optimizing a for loop in JS (push inside)

I have the following loop. The length is around 1500 points. But this snippit might get called multiple times on a page load (6-7).
buffer[xname] = [xname];
buffer[yname] = [yname];
for (var i = 0; i < rawdata.length; i++) {
buffer[xname].push( rawdata[i][0] );
buffer[yname].push( rawdata[i][1] );
}
I need to do this operation in the browser (it is used to condition the data before plotting them).
Currently this makes the browser very slow.
I tried to use a setTimeout() to ease the event loop a bit. That works but it takes seconds.
Is there any way to make this loop faster? Maybe some sort of mapping?
You can reduce the loop to half by doing:
buffer[xname] = [xname];
buffer[yname] = [yname];
var dataLength = rawdata.length;
for (var i = 0; i < dataLength / 2; i++) {
buffer[xname][i] = rawdata[i][0];
buffer[yname][i] = rawdata[i][1];
buffer[xname][dataLength - i -1] = rawdata[dataLength - i -1][0];
buffer[yname][dataLength - i -1] = rawdata[dataLength - i -1][1];
}
Not sure if the change between using push or direct assignment would impact enough to make the execution time the same.
Thanks to #royhowie
Why is array.push sometimes faster than array[n] = value?
If you have control over the source of rawdata, you might want to consider changing it so it can be used without additional processing.

JavaScript Automated Clicking

So, here's my issue.
I need to write a script to be run in the console (or via Greasemonkey) to automate clicking of certain links to check their output.
Each time one of these links is clicked, they essentially generate an image in a flash container to the left. The goal here is to be able to automate this so that the QC technicians do not have to click each of these thumbnails themselves.
Needless to say, there needs to be a delay between each "click" event and the next so that the user can view the large image and make sure it is okay.
Here is my script thus far:
function pausecomp(ms) {
ms = ms + new Date().getTime();
while (new Date() < ms){}
}
var itemlist, totalnumber, i;
itemlist = document.getElementsByClassName("image");
totalnumber = parseInt(document.getElementById("quickNavImage").childNodes[3].firstChild.firstChild.nodeValue.replace(/[0-9]* of /, ""));
for(i = 0; i < totalnumber; i = i + 1) {
console.log(i);
itemlist[i].childNodes[1].click();
pausecomp(3000);
}
Now, totalnumber gets me the total number of thumbnails, obviously, and then itemlist is a list of get-able elements so I can access the link itself.
If I run itemlist[0].childNodes[1].click() it works just fine. Same with 1, 2, 3, etc. However, in the loop, it does nothing and it simply crashes both Firefox and IE. I don't need cross-browser capability, but I'm confused.
There is a built-in JS function "setInterval(afunction, interval)" that keeps executing a given function every "interval" miliseconds (1000 = 1s).
This fiddle shows how to use setTimeout to work through an array. Here is the code:
var my_array = ["a", "b", "c", "d"];
function step(index) {
console.log("value of my_array at " + index + ":", my_array[index]);
if (index < my_array.length - 1)
setTimeout(step, 3000, index + 1);
}
setTimeout(step, 3000, 0);
Every 3 seconds, you'll see on the console something like:
value of my_array at x: v
where x is the index in the array and v is the corresponding value.
The problem with your code is that your pausecomp loop is a form of busy waiting. Let's suppose you have 10 items to go through. Your code will click an item, spin for 3 seconds, click an item, spin for 3 seconds, etc. All your clicks are doing is queuing events to be dispatched. However, these events are not dispatched until your code finishes executing. It finishes executing after all the clicks are queued and (roughly) 30 seconds (in this hypothetical scenario) have elapsed. If the number of elements is greater that's even worse.
Using setTimeout like above allows the JavaScript virtual machine to regain control and allows dispatching events. The documentation on setTimeout is available here.
People were correct with SetInterval.
For the record, here's the completed code:
/*global console, document, clearInterval, setInterval*/
var itemlist, totalnumber, i, counter;
i = 0;
function findmepeterpan() {
"use strict";
console.log("Currently viewing " + (i + 1));
itemlist[i].scrollIntoView(true);
document.getElementById("headline").scrollIntoView(true);
itemlist[i].style.borderColor = "red";
itemlist[i].style.borderWidth = "thick";
itemlist[i].childNodes[1].click();
i = i + 1;
if (i === totalnumber) {
clearInterval(counter);
console.log("And we're done! Hope you enjoyed it!");
}
}
function keepitup() {
"use strict";
if (i !== 0) {
itemlist[i - 1].style.borderColor = "transparent";
itemlist[i - 1].style.borderWidth = "medium";
}
findmepeterpan();
}
itemlist = document.getElementsByClassName("image");
totalnumber = parseInt(document.getElementById("quickNavImage").childNodes[3].firstChild.firstChild.nodeValue.replace(/[0-9]* of /, ""), 10);
counter = setInterval(keepitup, 1500);

how restricted is recursion in javascript?

I guess its to stop browsers getting nailed all the time by duff code but this:
function print(item) {
document.getElementById('output').innerHTML =
document.getElementById('output').innerHTML
+ item + '<br />';
}
function recur(myInt) {
print(myInt);
if (int < 10) {
for (i = 0; i <= 1; i++) {
recur(myInt+1);
}
}
}
produces:
0
1
2
3
4
5
6
7
8
9
10
10
and not the big old mess I get when I do:
function recur(myInt) {
print(myInt);
if (int < 10) {
for (i = 0; i <= 1; i++) {
var x = myInt + 1;
setTimeout("recur("+x+")");
}
}
}
Am I missing something or is this how you do recursion in JS? I am interested in navigating trees using recursion where you need to call the method for each of the children.
You are using a global variable as loop counter, that's why it only loops completely for the innermost call. When you return from that call, the counter is already beyond the loop end for all the other loops.
If you make a local variable:
function recur(int) {
print(int);
if (int < 10) {
for (var i = 0; i <= 1; i++) {
recur(int + 1);
}
}
}
The output is the same number of items as when using a timeout. When you use the timeout, the global variable doesn't cause the same problem, because the recursive calls are queued up and executed later, when you have exited out of the loop.
I know what your doing wrong. Recursion in functions maintains a certain scope, so your iterator (i) is actually increasing in each scope every time the loop runs once.
function recur(int) {
print(int);
if (int < 10) {
for (var i = 0; i <= 1; i++) {
recur(int+1);
}
}
}
Note it is now 'var i = 0' this will stop your iterators from over-writing eachother. When you were setting a timeout, it was allowing the first loop to finish running before it ran the rest, it would also be running off the window object, which may remove the closure of the last iterator.
Recursion is very little restricted in JavaScript. Unless your trees are very deep, it should be fine. Most trees, even with millions of elements, are fairly wide, so you get at most log(n) recursive calls on the stack, which isn't noramally a problem. setTimeout is certainly not needed. As in your first example, you're right that sometimes you need a guard clause to guarantee that the recursion bottoms out.

Categories

Resources