I have this Javascript/JQuery code:
$.ajax({...}).done(function() {
console.log('done');
});
for(var i = 0; i < 10; i++)
console.log(i);
Let's say the ajax request completes when the loop has reached the 5th iteration, will the browser suspend the loop execution and run the callback or will it wait for the loop to finish?
To make it more clear, is an output like this possible?
0
1
2
3
4
done
5
6
7
8
9
or will the output always be:
0
1
2
3
4
5
6
7
8
9
done
More in general I was wondering if the browser always pushes the callback, when triggered, at the bottom of the execution queue.
You could get both output example you describe, depending on the time the ajax request takes to complete.
EDIT: Note that this might lock your browser for a while, but it should not crash, and then prints something like ***** DONE! ***** 2828725
var promise = new $.Deferred(),
i = 1, j = 0, to = 5000000;
promise.done(function() {
document.write("***** DONE! *****\n" + i);
i = to;
});
setTimeout(function() {
promise.resolve();
}, 1000);
for(i = 1; i < to; ++i) {
console.log(++j);
//alert(++j);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
The test I did seems to show the loop must complete first
fiddle
time = new Date()
new Request.JSONP({
url: 'http://jsfiddle.net/echo/jsonp/',
onSuccess: function (response) {
console.log('done ' + (new Date()-time))
}
}).send();
for (var i = 0; i <= 65535; i++) {
for (var j = 0; j <= 10000; j++) {
if (i===65535 && j == 10000)
{
console.log('loop complete ' + (new Date()-time))
}
}
}
Related
I am having trouble understanding why the answer is 9. From my understanding adding the setTimeout function into a for loop means that the setTimeout function will run 3 times for each loop. So it loops 3 times and in each loop, setTimeout runs 3 times for a total of 9 times? I am missing the understanding.
var result = 0;
for (var i = 0; i < 3; i++) {
setTimeout(function() {
result += i;
}, 1000);
}
console.log(result) // answer is 9
Javascript is a single-thread system. setTimeout basically puts your request on the call stack to be executed after 1 second.
It is still fired in the scope of your function, but at the end of it, with a 1 second delay.
At the end of your function, i === 3 and because you execute it 3 times, you'll get result === 9
You can see this more clearly if you do this:
var result = 0;
for (var i = 0; i < 3; i++) {
setTimeout(function() {
result += i;
console.log("i: " + i);
console.log("result: " + result)
}, 1000);
}
You can wrap up your timeout, to break the dependency on i.
Do this by placing setTimeout in a function and pass i into it. that way, it doesn't matter what i is,
as we are using j which is scoped inside the new function.
var result = 0;
for (var i = 0; i < 3; i++) {
(function(j){
setTimeout(function() {
result += j;
console.log("i: " + i);
console.log("j: " + j);
console.log("result: " + result)
}, 1000);
})(i);
}
I Want to make a loop to live 2 seconds, then brake after.
This code wont work, the loop goes to end, it wont brake at 2 seconds. Why?
var stop = 0;
setTimeout(function() {
stop = 1;
}, 2000);
for (var i = 0; i < 10000; i++) {
console.log("wait" + stop);
if (stop == 1) break;
}
Is there a workarround?
A setTimeout callback will never interrupt a running synchronous loop. To achieve the desired result, you can change your loop head to
for (var i=0, timeout=Date.now()+2000; i<10000 && Date.now()<timeout; i++) …
Hi all when i am executing this piece of code i am getting 40 in my console log can some one plese explain me why
for (var i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);
}, 300000)
};
What you are getting on the console is the id returned by setTimeout(). If you run that code again you might get different value. We cannot predict this id, it is random.
If you want to print the values from 0-9 using setTimeout(), you need to take care of scope.
Using bind():
console.log('before loop');
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(this.i);
}.bind({
i: i
}), 1000)
}
console.log('after loop');
Using closures:
console.log('before loop');
for (var i = 0; i < 10; i++) {
(function(i) {
setTimeout(function() {
console.log(i); //<-- parameter i
}, 1000);
})(i); //<-- i from loop scope
}
console.log('after loop');
Print in increasing order of timeout.
console.log('before loop');
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(this.i);
}.bind({
i: i
}), 100 * i); //<-- note `* i`
}
console.log('after loop');
Your code will print 10 after 300.000 milliseconds.
Try setting it to a shorter period and you will see 10 printed.
What you probably see is linenumber in the console.
when I am executing this piece of code I am getting 40 in my console log
The reason is that setTimeout() moves the function from the execution queue, it will only be invoked after JavaScript has finished with the current execution queue.
Understanding JavaScript Timers
So I just wonder, if I have something like this:
var arr = [4,3,2,2]
setTimeout(function() {
arr.push(3)
}, 2) // 2 MS
for (var i = 0; i < arr.length; i++) {
arr.splice(i, 1)
arr.push(Math.floor(Math.random() * 7) + 2)
}
Is it possible that the timeout can execute anytime under the time of the loop, depending on how fast the JS is executed, or does the timeout wait for the loop to end or something?
I have a bubble sort function that when the a swap occurs it should show it visibly. But after lots of approaches it continues executing the loops without waiting for the animation to stop. (we are only allowed to use JavaScript). Is there a way to tell the website to wait for the animation to complete. Here is a snippet of my code:
for (var i = 0; i < len; i++)
{
for (var j = 0, swapping, endIndex = len - i; j < endIndex; j++)
{
if (marksArr[j] > marksArr[j + 1])
{
//swap objects
/*(function() {
var k = 0,
action = function() {
document.getElementById(coursesKey[j]).style.top = (parseInt(document.getElementById(coursesKey[j]).style.top) + 1) + 'px';
document.getElementById(coursesKey[j + 1]).style.top = (parseInt(document.getElementById(coursesKey[j+1]).style.top) - 1) + 'px';
k++;
if (k < difMoves) {
setTimeout(action, 200);
}
};
setTimeout(action, 200);
})();*/
}
}
}
As #cookie monster already explained, you can't block loops in JavaScript and update the UI using setTimeout() at the same time (this is because JavaScript is essentially single-threaded).
The most elegant solution would be "recording" each animation step while the for loops process the array, and then run the animation afterwards, e.g. using setTimeout(). Some time ago, I've implemented this approach for a similar question on StackOverflow; here's a demo: JSFiddle
The code can also be simplified:
function swap(list, i1, i2) {
var tmp = list[i1];
list[i1] = list[i2];
list[i2] = tmp;
}
function animateBubblesort(list) {
var animationSteps = [];
// Sort array
for (var n = list.length; n > 1; --n) {
for (var i = 0; i < n-1; ++i) {
if (list[i] > list[i+1]) {
swap(list, i, i+1);
// Add new step (clone of current array) to "animation queue"
animationSteps.push(list.slice(0));
}
}
}
// Print animated steps (using setInterval() for simplicity)
var count = 0,
interval = setInterval(function(){
console.log(animationSteps[count]);
if (++count >= animationSteps.length) {
clearInterval(interval);
}
}, 250);
}
animateBubblesort([5,8,2,4,1,9,7,3,0,6]);
DEMO
Another (less intuitive) possibility would be to implement the algorithm without loops in order to get control over when the next step of the algorithm is executed (so you have time for your animation). Here's an example: DEMO 2