I would like to check the efficiency of my functions, let's say to find a prime number, I wrote something like:
var counter = 0;
var myVar = setInterval(myTimer, 10)
function myTimer() {counter++}
//Function to be accessed
function isPrime(num){
my function
}
var prime = isPrime(x);
clearInterval(myVar);
console.log(counter);
My problem is that counter = 0in the end
Interestingly it would work if I would make an action with the timer, for example getting an html element and increase it's value.
Any idea?
thanks
//start timer with label
console.time("label");
doSomething();
//end timer and print to corresponding label
console.timeEnd("label");
function doSomething()
{
alert("stackoverflow bye!");
}
In cases where you have to measure performance console.time() and console.timeEnd() is your friend.
console.time(string) starts timer
console.timeEnd(string) ends timer and print in console
You should be aware of event loops in javascript to understand why your code didn't work as expected. The rule number 1 of event loop is, functions which are gonna work in async manner would be pushed in callBack queue. And the other functions would be pushed into call stack. Once all the functions in call stack got executed then only the functions in callBack queue will be executed one by one. No matter how much waiting time you gave.
.
.
var myVar = setInterval(myTimer, 10);
//myTimer will be put under a timer internally
//And will wait for 10 ms to enter into callBack queue
//Say this was happened in 1st millisecond
.
.
.
var prime = isPrime(x);
//isPrime(x) will be pushed into call stack and executed immediately
//if there is no other function in the stack
//Say this was happened in 5th millisecond
.
.
.
clearInterval(myVar);
//clearInterval(myVar) will be pushed into call stack and executed immediately
//if there is no other function in the stack.
//And simultaneously kill the timer which was created internally.
//Say this was happened in 7th millisecond
.
.
console.log(counter);
//Now, there was not at all a single chance to call the function myTimer.
//So the counter variable wouldn't be incremented.
//Thus it prints 0.
To do a proper instrumentation, you have to use the date object.
function isPrime(num){}
var prime, startTime, endTime;
startTime = Date.now();
prime = isPrime(x);
endTime = Date.now();
console.log(endTime - startTime, "ms taken to finish execution");
I can't exactly understand you're target. If you want to check how fast youre methods are set a timestamp, run the method and waiting for a callback. If its arrived set a new timestamp and compare both.
Related
I have a forEach() method that looks like this:
channels.forEach((channel) => {
var start = new Date().getTime();
fields.forEach(function(field) {
//stuff done here
});
var end = new Date().getTime();
var time = (end - start);
console.log(time)
});
I'd like to take the execution time for the first channel in the forEach() method, and estimate the rest of the loops based on that first completion time. Not sure if this is set up correctly for that, or where I should go from here
It is fundamentally correct, but you are printing the elapsed time of each channel, instead of just once, unless you are cancelling the test afterwards. I would suggest that you measure the time it takes to run over all the channels and take the average time for all, as this value will be more consistent/scientific for lack of a better word.
Also, the regular Date().getTime() function only has a precision down to one millisecond. You could switch to a library with a more precise nanosecond timer.
Try it with console.time() and console.timeEnd() as shown below:
channels.forEach((channel) => {
console.time("time taken");
fields.forEach(function(field) {
//stuff done here
});
console.timeEnd("time taken");
});
for (let i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
}
Biggest thing I'm confused about here - Why does this print 1,2,3,4,5 - All one second apart? Rather than incrementing one second, and taking one second longer each time we go through the for loop? I also have another variation that confuses me, where I do a console.log(i) as the last step in the for loop, and it just instantly posts 1-5. Any help here?
Coming from C#, for the record, not sure if the behaviour exists in C# or if I'm just a bit rusty.
Thanks!
It is actually quite simple. The for loop schedules the timer function for all five values. Then the timer function starts printing the numbers. Now the reason for them being printed 1 second apart is i*1000 in setTimeout. As a result, 1 will be printed 1 second after it has been scheduled, 2 will be printed 2 seconds after it has been scheduled, and approximately 1 second after 1 has been scheduled, and so on...
See the snippet below to understand how it works. Keep in mind that setTimeout does not block the execution of the for loop.
for (let i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
console.log("Print " + i + " after " + i +" seconds.");
}
console.log("for loop completed.");
setTimeout() will place your timer() into the queue.
for loop execute very quickly nearly immediately, each loop timer() will be placed into the queue with delays: 1,2,3,4,5 seconds respectively.
console.log(i) will print 1-5 because of the immediate execution of for loop.
I guess what the other answers have not touched upon is the event loop.
The event loop is a distinct execution thread than the main JS thread.
Your for loop would execute in the main JS thread, pushing each timeout on the event loop which would be executed in the event loop as scheduled. The time scale of events would look something like this.
I hope this is what you are looking for
System.Threading.Thread.Sleep(1000*i);
For one of my elements on my page, I want the text to change every ten seconds, and for the class to be changed. Text changing is easy, as is class changing, but I'm having trouble with my for loop, and I feel like I'm missing something.
I want to have the for loop choose a random faction in an array, and then apply that to the element. For my testing, I've been using console.log rather than DOM manipulation.
First, I set up my array:
var factions = ["Enforcers", "Reapers", "Ular Boys", "Roaches"];
Then, I want a variable that is a number chosen at random in reference to this array:
var x = factions[Math.floor(Math.random()*factions.length)];
From that, I want the ability to run the Math.floor and Math.random functions elsewhere.
function reDefine() {
x = factions[Math.floor(Math.random()*factions.length)];
console.log(x);
}
Finally, I want the for loop to run 200 times (I've chosen 200 times because it's far and beyond the time the user will be staying on the site), so I told it to count to 200 (i = 0; i < 200). After that, I wanted each time it iterated, to wait 10s, so I have a Timeout function with a delay of 10000 (milliseconds). Then, the code to reDefine and then, in the case of testing, console.log the new definition of the x variable.
function reChange() {
for (var i = 0; i < 200; i++) {
setTimeout(function() {
reDefine();
console.log("Chosen faction is now: " + x);
}, 10000);
}
}
Instead of counting to 1 (the first iteration), waiting 10000, and then redefining x, it redefines x two hundred times, then logs them all.
Is there something I'm specifically doing wrong here, perhaps with the Timeout function?
Is there something I'm specifically doing wrong here, perhaps with the Timeout function?
Yes! You're scheduling a bunch of deferred callbacks, but not actually waiting until one has finished to schedule the next.
You can fix that with something as simple as:
function reChange(currentIndex) {
setTimeout(function() {
reDefine();
console.log("Chosen faction is now: " + factions[currentIndex]);
// If we haven't gotten to the end of the list, queue up another one
var nextIndex = ++currentIndex;
if (nextIndex < factions.length) {
// Enqueue the next faction
reChange(nextIndex);
}
}, 10000);
}
Make sure to note that the function without the timeout has closure over the value of currentIndex for each call of reChange. That is, the next invocation does not replace currentIndex in any previous timeout, since primitives (including numbers) are passed by value. Closure in JS can be a tricky thing.
The core problem is that your execution right now looks like:
for each item
wait
log
rather than:
for the current item
wait
log
repeat
Because JS is single-threaded (for most intents and purposes), setTimeout adds a callback to be executed later. It doesn't block until the timeout has expired, like a traditional sleep would do.
This question already has answers here:
JS setInterval executes only once
(2 answers)
Closed 6 years ago.
I can't get this code to do anything beyond counting down to 29 from 30. Does anyone have any insight or hints as to what I am doing wrong to cause it to only run once? I checked to make sure that all the functions are being called with console.logs on game.time (except the clearInterval one since it stops already after the first time through). How do I get the setInterval to keep looping until 0? Thanks in advance for any help! :)
//game object to contain variables and methods
var game = {
// variable for time
time: 30,
// Start button onclick creates the time remaining object and calls the forloop to start
start: function() {
// $("#time").html(game.time);
game.countdown = setInterval(game.count(), 1000);
}, //end of start function
//what the set interval does which is subtract one second from game.time
count: function() {
game.time--;
// if statement to check when time gets to zero
if (game.time <= 0) {
game.stop();
}
// puts the current time left on the page
else {
$("#time").html(game.time);
}
}, // End of count function
// stops the set interval
stop: function() {
clearInterval(game.countdown);
}, // end of stop function
}; // end game object
// Start button click calls the start method
$("#start").click(game.start);
setInterval takes a function refererence as a parameter, it should look like:
setInterval(game.count, 1000)
When you write it as game.count(), you're calling the count() method once, which is evaluated immediately.
Then, setInterval's signature will use the return value from that method instead of a function reference:
setInterval(whatever_the_return_value_was, 1000);
By passing only the reference (as game.count), the timer should work as expected. It will call the reference by itself, every 1000ms.
(MDN docs)
I'm working on a simon game(the one you follow the color pattern). It makes it through the computers 1st turn and my 1st turn but trying to do a setTimeout between each computer choice is causing an infinite loop with the do while statement or playing both choices at the same time if I use for loop. The highlightDiv function just does a toggleClass on the div, then a setTimeout to toggle the class back off. And the audioStart function uses a switch statement to determine which sound to play and then a setTimeout of half a second to play that sound. I thought this setTimeout on the increment would allow enough time for those two things to happen before it incremented and then did the next index in the computerChoice array. This is the codepen if that is easier: http://codepen.io/RawleJuglal/pen/pgRVKd
var computerChoice = ["red", "yellow"],index=0;
function computerPattern(cPattern, index){
console.log("Entered computer pattern function");
console.log("This is cPattern");
console.log(cPattern);
console.log("This is index: "+ index);
if(index !== cPattern.length)
{
highlightDiv(cPattern[index]);
audioStart(cPattern[index]);
index++;
computerPattern(cPattern, index);
}
else
{
index=0;
}
console.log("Leaving computerPattern function");
}
computerPattern(computerChoice, index);
Javascript is single threaded, and the concept of timeouts means that you place a function on a special queue, which is to execute your callbacks when their time is due. now, since in your code, the i variable is being updated only in the timeout function, which is only after 3 seconds, it means that the body of the loop will run again and again until 3 seconds are met.
in 3 seconds, javascript can run thousands of iterations, and each iteration registers another timeout, which means that your event queue is blasted and your single thread will have hard time completing all those tasks until i is finally reaching cPattern.length, if ever.
your solution might be using some sort of setInterval which has a callback that does what you want, and stops on some iteration variable that increments every time, let's say like this:
var interval = setInterval(function(){
console.log(cPattern[i]);
highlightDiv(cPattern[i]);
audioStart(cPattern[i]);
i++;
if(i >= cPattern.length){
clearInterval(interval);
}
},
2000);
Your timeout function is never called because you don't give it a chance. As long as your code is running (your loop), the browser can't run the scheduled scripts, which use the same thread. You will have to rethink the code.
You're incrementing a variable called i within the anonymous function delegate that you're passing to setTimeout. The locally-scoped variable i on which the do-while loop depends is never updated.
Depending on the functionality you're looking for, you can increment the variable i while it's still in scope, then use a closure to pass a snapshot of its value to the setTimeout function delegate.
function run(){
var i = 0
do{
(function(i){
setTimeout(function(){
alert(i);
},1000);
})(i++)
}
while(i < 2);
}
run();