I have a jsFiddle that I've been messing around with, trying to get my little game to become more organized with classes and such, but when I request an animation frame, passing in the objects (each frame does a few functions with each object), I get a Maximum call stack size error. How can I fix this without abandoning my classes?
The jsFiddle:
http://jsfiddle.net/Blawkbuilder/Q5U3X/109/
the line I suspect to be the culpurit:
window.requestAnimationFrame(draw(p1,p2));
but the line the console links to occurs somewhere in jquery:
} else if ( !rhtml.test( elem ) ) {
Fix? I'm a bit new to javascript.
(If needed, here is the previous, not class based version that still functions how I want this too)
http://jsfiddle.net/Blawkbuilder/9hmca/131/
requestAnimationFrame takes a callback. You are evaluating draw(p1, p2) and passing its return value to requestAnimationFrame. You should change to something like this:
requestAnimationFrame(function() { draw(p1, p2); });
This is similar to setInterval/setTimeout.
requestAnimationFrame takes a callback function with no arguments as a parameter. The reason you're getting a stack overflow is that you're providing the parameter draw(p1, p2) (rather than draw), which actually invokes the draw function, which then makes the same mistake of invoking the draw function ... (and so forth). You're doing it correctly in the second jsFiddle.
To get around this, you need draw to not take any parameters. Alternatively, create a "wrapper" function that doesn't take any parameters, which itself simply invokes draw with the appropriate parameters. The simplest way to do this do something like requestAnimationFrame(function() {draw(p1, p2); }) as the other answer suggests.
By the way, telling you this is metaphorically giving you a fish, rather than teaching you how to fish. To really understand this, you need to understand a bit more about functional programming, which can get a little abstract. In this example, understand that functions are nothing more than objects that have the special property of being "callable" (or "invokable"). requestAnimationFrame is a function whose first parameter, callback, is another function. requestAnimationFrame is expecting that callback is callable, in other words. But you're giving it the result of calling the function, rather than the function itself.
The reason function() {draw(p1, p2);} works is that the function() { ... } syntax constructs an anonymous function -- a function without a name, but still a function that can be invoked.
Related
I was writing some code for a widget in "Scriptable" that shows random word at a certain time. The widget calls itself with a timeout, on iPad. But it's exceeding the stack size. How do I solve this? I am using Javascript within "Scriptable" framework, so I don't have much freedom.
kanjiObj: Object; kanjiKeys: List; Timer().schedule(timeinterval, repeat, callback)
var randomNum = Math.floor(Math.random()*150)+1
var kanji = kanjiKeys[randomNum]
var kanjiMeaning = kanjiObj[kanjiKeys[randomNum]]
if(config.runsInWidget){
let widget = createWidget()
Script.setWidget(widget)
Script.complete()
function createWidget(){
let widget = new ListWidget()
widget.addText(kanji + "=>" + kanjiMeaning)
widget.wait = new Timer().schedule(1000*60*60, 150, createWidget())
In your case, you are calling the createWidget() function recursively by mistake. Your intention was different, you wanted to pass the function as a parameter to the schedule function, which accepts a function callback as the last parameter.
So you have to change to
widget.wait = new Timer().schedule(1000*60*60, 150, () => createWidget())
or
widget.wait = new Timer().schedule(1000*60*60, 150, createWidget)
But since this question is about "call stack size exceeded" people who have a different kind of this problem could stumble upon it, so I will answer in a general way below as well.
Programming is about recognizing patterns, so what you have in your code is a pattern (structure) of an infinite recursive call
function someFunction() {
// ... code before the recursive call that never returns from this function
// an unconditional call (or a conditional chain that is always true)
// of the function itself in the function scope instead of inside a callback/lambda
someFunction()
// ... could be more code, which does not matter,
// until the pattern above still holds true
}
So a structure (pattern) like this will result in an infinite recursive call, which eventually ends with a maximum call stack size exceeded. Call stack size is limited and an infinite recursive call eventually fills it up.
Javascript does not have built-in tail-recursion optimization (in practice, see compatibility), but in programming languages that do, if the function is tail-recursive, it would be optimized to a loop. In the case of an infinite tail-recursive function it would be optimized to an infinite loop, which would not fill the call stack, it would just loop forever (it would be working, but if not implemented correctly, it could make the application unresponsive).
So to resolve a problem like this in general, one has to break this pattern by breaking any (at least one) of the conditions above. This is the list:
code before the recursive call that never returns from this function
add a conditional return statement (also called a stop condition)
an unconditional call (or a conditional chain that is always true) to the function itself in the function scope instead of inside a callback/lambda
make the call conditional (make sure the condition chain can be false) or put it inside a callback/lambda. When you put it inside a
callback/lambda, then a different pattern applies (you have to check
the logic inside the call that will be calling the callback), but
calling the callback still has to be conditional, it has to have a
limit at some point.
after making a change, the code that is after the call, needs to be checked for the same pattern again, if the pattern is there again, break it in a similar way. Keep repeating this until the whole function does not form the pattern anymore - has stop condition(s) where needed.
In cases when you do need an infinite recursive call and the function is tail-recursive and your language does not support tail-recursion optimization, you would need to do the tail optimization yourself or use a library/framework that lets you do that.
If this does not solve your problem, have a look at the answers in this question that has collected a lot of reasons why a "maximum call stack size exceeded" might happen in Javascript.
I am reading a book called You don't know JS: Async and Performance. They give the following example of a problem with nested callbacks and I was wondering if someone could elaborate on the specifics for me.
doA (function(){
doC();
doD(function(){
doF();
})
doE();
});
doB();
According to the author, the code will execute in the order denoted alphabetically. Meaning doA, then doB ... . I may have been able to guess this based on experience, but I am trying to get a better grasp as to exactly why this happens.
Edit: I posted the question because the example in the book didn't make any sense to me and I was hoping to get some clarification. Maybe I should have just said that instead of trying to rescue the author with some explanation. I edited the question a little to try and make that clear.
Is it because the event loop runs for the entire outer "wrapper" first before it starts the inner wrapper?
No. If the order of execution really is A,B,C,D,E,F, then it is because that is how the functions are written to invoke their callbacks. If the functions were written differently, it could just as easily be A,C,D,E,F,B or A,C,D,F,E,B or, it could even just be A,B, if A does not accept a callback function.
All of this speculation...
Here is what I think is happening. The event loop is first created as doA and doB because JavaScript is not really "concerned" with the contents of those lines at first. When JavaScript runs the line doA(function... it then adds the callback function to the end of the event loop placing doC and doD behind doB.
... is more or less nonsense.
Here is a drastically simplified example:
function doA(callback) { callback(); }
doA(function () {
doB()
});
doC();
Here, the order is A,B,C because that is how A is written.
However, if we change doA so it invokes its callback asynchronously...
function doA(callback) { setTimeout(callback); }
... then the order changes completely to A,C,B.
This has nothing to do with JavaScript being "concerned" with any of the inner or outer code, or where JavaScript "chooses" to place the callbacks in the "event loop". These are not real things. JavaScript doesn't "choose" to do anything. It just executes your code. It's entirely about what each function does and whether the function accepts a callback and how that callback is invoked.
I would like to know the difference between 2 implementations of callback functions.
This:
$("#button").on('click', function () {
//do something
});
Versus having the function already defined.
$("#button").on('click', btnFunction);
function btnFunction() {
//do something
}
Are there any implications with one compared to another? Performance-wise is one faster?
The first uses an anonymous function and the second does not. There's no difference in both.
See:
Why do you need to invoke an anonymous function on the same line?
Some folks prefer the second form because it gives a function name when using the debugger and tracing, but there are ways to get the same functionality in the first form.
If you are attaching and removing the event handler based on changing conditions, the second form is much easier to maintain, however.
There's no difference at all, and there's no performance issue with neither one of them. The only difference is that in one of them you're defining the callback function as an anonymous function, this way you cannot reuse it.
The other way, where you define it else where and named it and then pass it as a callback, you're defining a function that you can later reuse in another part of your code.
For example: if you want to do something when the document is ready, and then do se exact same thing when some one press a button you can use something like this:
function getData() {
//do something
}
$(function() {
// Call the function once the DOM is ready
getData();
});
// Call the same function when the button is clicked
$("#refresh_button").on('click', getData);
In most cases the first one will be used, called Anonymous Functions
The second one will be used when the function is not only used inlined here, but also needs to be reused somewhere else.
But anyway it could be a personal preference.
The only real difference you could see is that stack trace (if an exception is thrown for example) will be better, i.e. easier to debug, when using the second one.
Just reuse-ability.
In the second case, you could call btnFunction() somewhere else if need be.
If I had the following object and prototyped functionality added on.
function Hello (input){
this.input = input
}
Hello.prototype.ajaxcall = function(id){
$.get("/ajax/method", {parameter:input}, function(data){
$("#"id).html(data);
});
}
Forgive the syntax if not completely correct but what it should be doing is taking in an element id, performing an ajax call and assigning the ajax call result to the innerHTML of the id. Will the fact that the ajaxcall function is shared across all instances of an object cause any problems with regards to what data will be assigned to which id if for example 20 object were all created together and had this function called immediately?
If this is the case, does it make sense to put asyncronous methods inside the object constructor instead?
What would happen if 20 objects would be created and the ajaxcall function would be called? Nothing much. The ajax calls would run asynchronously. When they have finished they are queued so that they run on the main thread when the current running operation on the main thread finished.
So the callback functions run all synchronous in a queue next time there's time for it. Nothing bad can happen here.
I don't understand your question about the constructor. What would that change? If you use your Hello objects they have an instance variable. This is is enclosed in the callback closure . Creating a new function doesn't change the value in another callback function.
If you use the same IDs the content could flash when the text changes and you don't know which callback would be ran last but that's the worst thing that could happen.
There should be no issue. You're calling the function 20 distinct times with 20 different ids.
Conceptually though. I'm not seeing why this is part of your object. The function does not use anything at all from the object itself.
This particular example would work. Your function makes no use of any instance variables, so it doesn't really make sense to declare it that way, but it makes even less sense to move it into the constructor. Still it will work because the id argument will not be shared between calls.
EDIT: So now that you've changed it so that it does use an instance variable you've got the syntax wrong, it needs to be
{parameter : this.input}
But aside from that it will still work. The asynchronous behaviour is not a problem for the code shown.
I learn now that a callback is function that pass to argument.
but I can do it without so what is the point?
for example
function i()
{
alert("callback");
}
function p(a)
{
for(r=0;r<100;r++)
{document.write(r);}
a();
}
p(i);
or
function i()
{
alert("callback");
}
function p()
{
for(r=0;r<100;r++)
{document.write(r);}
i();}
I searched but could not find an answer
Callbacks are usually used when you want to do something with some data that isn't immediately available.
For example, to process some data from an HTTP response when the response arrives or to perform an action based on where a mouse click occurred when the mouse button is clicked.
So to take you example, yes if you want to call i() in function p() you can just go ahead and do that. But what if you want a function just like p() accept that it calls j() at the end instead of i()? Well, that's easy, you pass a function as a parameter for p() to call at the end instead of hardcoding it.
It's about flexibility. There's no need to do it for the sake of doing it, but there are many cases where it's useful.
So let me try and come up with a simple example, let's say we have a function called sum() that adds up all the elements of an array. Now let's say somewhere in our program we want to sum not all the elements, but some of the elements, maybe only the elements over a certain value, or every other element. If we set up sum so that it could take, in addition to the array to work on, a function parameter that will call filter (which if left null, we'll just sum all the elements by default), we could make our sum() function much more useful and avoid writing a whole bunch of different sum functions.
Also, as Quentin already answered, it's especially useful for asychronous functions.