admin管理员组文章数量:1391969
I was goofing around with JavaScript, and a notice a strange behavior (strange for me at least. . .)
So I did a SSCCE here it goes:
I have a div named "myDiv"
function changeText(text){
document.getElementById("myDiv").innerHTML=text;
}
function recursiveCall(counter){
if(counter){
setTimeout(function(){
recursiveCall(--counter);
changeText(counter);
},750);
}
}
recursiveCall(10);
Live example: /
So I'm changing the text on the div, and what happens is that the text goes from 9 to 0, while I thought that it was suppose to go from 0 to 9, since the recursive changeText(counter);
call is before calling the method that actually changes the text.
I was goofing around with JavaScript, and a notice a strange behavior (strange for me at least. . .)
So I did a SSCCE here it goes:
I have a div named "myDiv"
function changeText(text){
document.getElementById("myDiv").innerHTML=text;
}
function recursiveCall(counter){
if(counter){
setTimeout(function(){
recursiveCall(--counter);
changeText(counter);
},750);
}
}
recursiveCall(10);
Live example: http://jsfiddle/T645X/
So I'm changing the text on the div, and what happens is that the text goes from 9 to 0, while I thought that it was suppose to go from 0 to 9, since the recursive changeText(counter);
call is before calling the method that actually changes the text.
3 Answers
Reset to default 8The function contains a timeout which is asynchronous.
setTimeout(function(){
recursiveCall(--counter);// calls the next function, which will call the next
// and print in a timeout
changeText(counter); // print
},750);
The text is changed before the recursive call hits the timeout.
If you'd like to, you can move the print call from outside the timeout, which would result in the expected behavior as such:
function recursiveCall(counter){
if(counter){
recursiveCall(--counter);
setTimeout(function(){
changeText(counter);
},750);
}
}
(Although, note that here the printing is not timed apart, and we're relying somewhat on undefined behavior assuming it'd print first just because we put the timer first)
If you would like it to still print in delays, you can tell the function it's done. Recursion will still be done initially, but each level will tell the level above it that it is done:
function recursiveCall(counter,done){
if(counter){
// note how recursion is done before the timeouts
recursiveCall(counter-1,function(){ //note the function
setTimeout(function(){ //When I'm done, change the text and let the
changeText(counter-1); //next one know it's its turn.
done(); // notify the next in line.
},750);
});
}else{
done(); //If I'm the end condition, start working.
}
}
Here is a fiddle implementing this.
Strictly speaking there is no recursion here.
The call to setTimeout
just adds a callback to a list of scheduled timer events.
Much of the time, your browser is just sat there waiting for events, it processes those (i.e. runs your event handlers) and then goes back to waiting for events.
So in this case what you're doing is:
recursiveCall(10)
timer event and callback added to the queue
function exits
... waits 750 ms ...
timer event fires, callback pulled from the queue and invoked
-> recursiveCall(9) invoked
-> timer event and callback added to the queue
-> changeText(9) invoked
callback function exits
... waits 750 ms ...
timer event fires, callback pulled from the queue and invoked
-> recursiveCall(8) invoked
-> timer event and callback added to the queue
-> changeText(8) invoked
callback function exits
and so on...
I call this pseudo-recursion, because although it looks somewhat like classical recursion, each invocation starts at the same "stack frame", i.e. if you asked for a stack trace there would typically only be one (or in your case sometimes two) instance of recursiveCall
present at a time.
One thing to understand is that it's not recursion in the first place; if your function didn't have a proper exit clause, this could go on forever without running into a blown stack.
The reason is that any function you pass to setTimeout()
is run outside of the current execution context; in other words, the code "breaks out" of your function.
If you want a recursive call with 750ms in between them, you could do something like this:
function recursiveCall(counter, fn)
{
if (counter) {
recursiveCall(--counter, function() {
changeText(counter);
setTimeout(fn, 750);
});
} else if (fn) {
fn(); // start chain backwards
}
}
It creates a chain of callbacks when it recurses and the exit clause sets the whole chain motion, backwards :)
本文标签: How does Javascript manages recursive callsStack Overflow
版权声明:本文标题:How does Javascript manages recursive calls? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744733967a2622212.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论